<!doctype html>

<html>
<head>
  <link rel="shortcut icon" href="static/images/favicon.ico" type="image/x-icon">
  <title>style.js (Closure Library API Documentation - JavaScript)</title>
  <link rel="stylesheet" href="static/css/base.css">
  <link rel="stylesheet" href="static/css/doc.css">
  <link rel="stylesheet" href="static/css/sidetree.css">
  <link rel="stylesheet" href="static/css/prettify.css">

  <script>
     var _staticFilePath = "static/";
     var _typeTreeName = "goog";
     var _fileTreeName = "Source";
  </script>

  <script src="static/js/doc.js">
  </script>


  <meta charset="utf8">
</head>

<body onload="grokdoc.onLoad();">

<div id="header">
  <div class="g-section g-tpl-50-50 g-split">
    <div class="g-unit g-first">
      <a id="logo" href="index.html">Closure Library API Documentation</a>
    </div>

    <div class="g-unit">
      <div class="g-c">
        <strong>Go to class or file:</strong>
        <input type="text" id="ac">
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<h2><a href="closure_goog_style_style.js.html">style.js</a></h2>

<pre class="prettyprint lang-js">
<a name="line1"></a>// Copyright 2006 The Closure Library Authors. All Rights Reserved.
<a name="line2"></a>//
<a name="line3"></a>// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
<a name="line4"></a>// you may not use this file except in compliance with the License.
<a name="line5"></a>// You may obtain a copy of the License at
<a name="line6"></a>//
<a name="line7"></a>//      http://www.apache.org/licenses/LICENSE-2.0
<a name="line8"></a>//
<a name="line9"></a>// Unless required by applicable law or agreed to in writing, software
<a name="line10"></a>// distributed under the License is distributed on an &quot;AS-IS&quot; BASIS,
<a name="line11"></a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a name="line12"></a>// See the License for the specific language governing permissions and
<a name="line13"></a>// limitations under the License.
<a name="line14"></a>
<a name="line15"></a>/**
<a name="line16"></a> * @fileoverview Utilities for element styles.
<a name="line17"></a> *
<a name="line18"></a> * @see ../demos/inline_block_quirks.html
<a name="line19"></a> * @see ../demos/inline_block_standards.html
<a name="line20"></a> * @see ../demos/style_viewport.html
<a name="line21"></a> */
<a name="line22"></a>
<a name="line23"></a>goog.provide(&#39;goog.style&#39;);
<a name="line24"></a>
<a name="line25"></a>
<a name="line26"></a>goog.require(&#39;goog.array&#39;);
<a name="line27"></a>goog.require(&#39;goog.dom&#39;);
<a name="line28"></a>goog.require(&#39;goog.dom.vendor&#39;);
<a name="line29"></a>goog.require(&#39;goog.math.Box&#39;);
<a name="line30"></a>goog.require(&#39;goog.math.Coordinate&#39;);
<a name="line31"></a>goog.require(&#39;goog.math.Rect&#39;);
<a name="line32"></a>goog.require(&#39;goog.math.Size&#39;);
<a name="line33"></a>goog.require(&#39;goog.object&#39;);
<a name="line34"></a>goog.require(&#39;goog.string&#39;);
<a name="line35"></a>goog.require(&#39;goog.userAgent&#39;);
<a name="line36"></a>
<a name="line37"></a>
<a name="line38"></a>/**
<a name="line39"></a> * Sets a style value on an element.
<a name="line40"></a> *
<a name="line41"></a> * This function is not indended to patch issues in the browser&#39;s style
<a name="line42"></a> * handling, but to allow easy programmatic access to setting dash-separated
<a name="line43"></a> * style properties.  An example is setting a batch of properties from a data
<a name="line44"></a> * object without overwriting old styles.  When possible, use native APIs:
<a name="line45"></a> * elem.style.propertyKey = &#39;value&#39; or (if obliterating old styles is fine)
<a name="line46"></a> * elem.style.cssText = &#39;property1: value1; property2: value2&#39;.
<a name="line47"></a> *
<a name="line48"></a> * @param {Element} element The element to change.
<a name="line49"></a> * @param {string|Object} style If a string, a style name. If an object, a hash
<a name="line50"></a> *     of style names to style values.
<a name="line51"></a> * @param {string|number|boolean=} opt_value If style was a string, then this
<a name="line52"></a> *     should be the value.
<a name="line53"></a> */
<a name="line54"></a>goog.style.setStyle = function(element, style, opt_value) {
<a name="line55"></a>  if (goog.isString(style)) {
<a name="line56"></a>    goog.style.setStyle_(element, opt_value, style);
<a name="line57"></a>  } else {
<a name="line58"></a>    goog.object.forEach(style, goog.partial(goog.style.setStyle_, element));
<a name="line59"></a>  }
<a name="line60"></a>};
<a name="line61"></a>
<a name="line62"></a>
<a name="line63"></a>/**
<a name="line64"></a> * Sets a style value on an element, with parameters swapped to work with
<a name="line65"></a> * {@code goog.object.forEach()}. Prepends a vendor-specific prefix when
<a name="line66"></a> * necessary.
<a name="line67"></a> * @param {Element} element The element to change.
<a name="line68"></a> * @param {string|number|boolean|undefined} value Style value.
<a name="line69"></a> * @param {string} style Style name.
<a name="line70"></a> * @private
<a name="line71"></a> */
<a name="line72"></a>goog.style.setStyle_ = function(element, value, style) {
<a name="line73"></a>  var propertyName = goog.style.getVendorJsStyleName_(element, style);
<a name="line74"></a>
<a name="line75"></a>  if (propertyName) {
<a name="line76"></a>    element.style[propertyName] = value;
<a name="line77"></a>  }
<a name="line78"></a>};
<a name="line79"></a>
<a name="line80"></a>
<a name="line81"></a>/**
<a name="line82"></a> * Returns the style property name in camel-case. If it does not exist and a
<a name="line83"></a> * vendor-specific version of the property does exist, then return the vendor-
<a name="line84"></a> * specific property name instead.
<a name="line85"></a> * @param {Element} element The element to change.
<a name="line86"></a> * @param {string} style Style name.
<a name="line87"></a> * @return {string} Vendor-specific style.
<a name="line88"></a> * @private
<a name="line89"></a> */
<a name="line90"></a>goog.style.getVendorJsStyleName_ = function(element, style) {
<a name="line91"></a>  var camelStyle = goog.string.toCamelCase(style);
<a name="line92"></a>
<a name="line93"></a>  if (element.style[camelStyle] === undefined) {
<a name="line94"></a>    var prefixedStyle = goog.dom.vendor.getVendorJsPrefix() +
<a name="line95"></a>        goog.string.toTitleCase(style);
<a name="line96"></a>
<a name="line97"></a>    if (element.style[prefixedStyle] !== undefined) {
<a name="line98"></a>      return prefixedStyle;
<a name="line99"></a>    }
<a name="line100"></a>  }
<a name="line101"></a>
<a name="line102"></a>  return camelStyle;
<a name="line103"></a>};
<a name="line104"></a>
<a name="line105"></a>
<a name="line106"></a>/**
<a name="line107"></a> * Returns the style property name in CSS notation. If it does not exist and a
<a name="line108"></a> * vendor-specific version of the property does exist, then return the vendor-
<a name="line109"></a> * specific property name instead.
<a name="line110"></a> * @param {Element} element The element to change.
<a name="line111"></a> * @param {string} style Style name.
<a name="line112"></a> * @return {string} Vendor-specific style.
<a name="line113"></a> * @private
<a name="line114"></a> */
<a name="line115"></a>goog.style.getVendorStyleName_ = function(element, style) {
<a name="line116"></a>  var camelStyle = goog.string.toCamelCase(style);
<a name="line117"></a>
<a name="line118"></a>  if (element.style[camelStyle] === undefined) {
<a name="line119"></a>    var prefixedStyle = goog.dom.vendor.getVendorJsPrefix() +
<a name="line120"></a>        goog.string.toTitleCase(style);
<a name="line121"></a>
<a name="line122"></a>    if (element.style[prefixedStyle] !== undefined) {
<a name="line123"></a>      return goog.dom.vendor.getVendorPrefix() + &#39;-&#39; + style;
<a name="line124"></a>    }
<a name="line125"></a>  }
<a name="line126"></a>
<a name="line127"></a>  return style;
<a name="line128"></a>};
<a name="line129"></a>
<a name="line130"></a>
<a name="line131"></a>/**
<a name="line132"></a> * Retrieves an explicitly-set style value of a node. This returns &#39;&#39; if there
<a name="line133"></a> * isn&#39;t a style attribute on the element or if this style property has not been
<a name="line134"></a> * explicitly set in script.
<a name="line135"></a> *
<a name="line136"></a> * @param {Element} element Element to get style of.
<a name="line137"></a> * @param {string} property Property to get, css-style (if you have a camel-case
<a name="line138"></a> * property, use element.style[style]).
<a name="line139"></a> * @return {string} Style value.
<a name="line140"></a> */
<a name="line141"></a>goog.style.getStyle = function(element, property) {
<a name="line142"></a>  // element.style is &#39;&#39; for well-known properties which are unset.
<a name="line143"></a>  // For for browser specific styles as &#39;filter&#39; is undefined
<a name="line144"></a>  // so we need to return &#39;&#39; explicitly to make it consistent across
<a name="line145"></a>  // browsers.
<a name="line146"></a>  var styleValue = element.style[goog.string.toCamelCase(property)];
<a name="line147"></a>
<a name="line148"></a>  // Using typeof here because of a bug in Safari 5.1, where this value
<a name="line149"></a>  // was undefined, but === undefined returned false.
<a name="line150"></a>  if (typeof(styleValue) !== &#39;undefined&#39;) {
<a name="line151"></a>    return styleValue;
<a name="line152"></a>  }
<a name="line153"></a>
<a name="line154"></a>  return element.style[goog.style.getVendorJsStyleName_(element, property)] ||
<a name="line155"></a>      &#39;&#39;;
<a name="line156"></a>};
<a name="line157"></a>
<a name="line158"></a>
<a name="line159"></a>/**
<a name="line160"></a> * Retrieves a computed style value of a node. It returns empty string if the
<a name="line161"></a> * value cannot be computed (which will be the case in Internet Explorer) or
<a name="line162"></a> * &quot;none&quot; if the property requested is an SVG one and it has not been
<a name="line163"></a> * explicitly set (firefox and webkit).
<a name="line164"></a> *
<a name="line165"></a> * @param {Element} element Element to get style of.
<a name="line166"></a> * @param {string} property Property to get (camel-case).
<a name="line167"></a> * @return {string} Style value.
<a name="line168"></a> */
<a name="line169"></a>goog.style.getComputedStyle = function(element, property) {
<a name="line170"></a>  var doc = goog.dom.getOwnerDocument(element);
<a name="line171"></a>  if (doc.defaultView &amp;&amp; doc.defaultView.getComputedStyle) {
<a name="line172"></a>    var styles = doc.defaultView.getComputedStyle(element, null);
<a name="line173"></a>    if (styles) {
<a name="line174"></a>      // element.style[..] is undefined for browser specific styles
<a name="line175"></a>      // as &#39;filter&#39;.
<a name="line176"></a>      return styles[property] || styles.getPropertyValue(property) || &#39;&#39;;
<a name="line177"></a>    }
<a name="line178"></a>  }
<a name="line179"></a>
<a name="line180"></a>  return &#39;&#39;;
<a name="line181"></a>};
<a name="line182"></a>
<a name="line183"></a>
<a name="line184"></a>/**
<a name="line185"></a> * Gets the cascaded style value of a node, or null if the value cannot be
<a name="line186"></a> * computed (only Internet Explorer can do this).
<a name="line187"></a> *
<a name="line188"></a> * @param {Element} element Element to get style of.
<a name="line189"></a> * @param {string} style Property to get (camel-case).
<a name="line190"></a> * @return {string} Style value.
<a name="line191"></a> */
<a name="line192"></a>goog.style.getCascadedStyle = function(element, style) {
<a name="line193"></a>  // TODO(nicksantos): This should be documented to return null. #fixTypes
<a name="line194"></a>  return element.currentStyle ? element.currentStyle[style] : null;
<a name="line195"></a>};
<a name="line196"></a>
<a name="line197"></a>
<a name="line198"></a>/**
<a name="line199"></a> * Cross-browser pseudo get computed style. It returns the computed style where
<a name="line200"></a> * available. If not available it tries the cascaded style value (IE
<a name="line201"></a> * currentStyle) and in worst case the inline style value.  It shouldn&#39;t be
<a name="line202"></a> * called directly, see http://wiki/Main/ComputedStyleVsCascadedStyle for
<a name="line203"></a> * discussion.
<a name="line204"></a> *
<a name="line205"></a> * @param {Element} element Element to get style of.
<a name="line206"></a> * @param {string} style Property to get (must be camelCase, not css-style.).
<a name="line207"></a> * @return {string} Style value.
<a name="line208"></a> * @private
<a name="line209"></a> */
<a name="line210"></a>goog.style.getStyle_ = function(element, style) {
<a name="line211"></a>  return goog.style.getComputedStyle(element, style) ||
<a name="line212"></a>         goog.style.getCascadedStyle(element, style) ||
<a name="line213"></a>         (element.style &amp;&amp; element.style[style]);
<a name="line214"></a>};
<a name="line215"></a>
<a name="line216"></a>
<a name="line217"></a>/**
<a name="line218"></a> * Retrieves the computed value of the position CSS attribute.
<a name="line219"></a> * @param {Element} element The element to get the position of.
<a name="line220"></a> * @return {string} Position value.
<a name="line221"></a> */
<a name="line222"></a>goog.style.getComputedPosition = function(element) {
<a name="line223"></a>  return goog.style.getStyle_(element, &#39;position&#39;);
<a name="line224"></a>};
<a name="line225"></a>
<a name="line226"></a>
<a name="line227"></a>/**
<a name="line228"></a> * Retrieves the computed background color string for a given element. The
<a name="line229"></a> * string returned is suitable for assigning to another element&#39;s
<a name="line230"></a> * background-color, but is not guaranteed to be in any particular string
<a name="line231"></a> * format. Accessing the color in a numeric form may not be possible in all
<a name="line232"></a> * browsers or with all input.
<a name="line233"></a> *
<a name="line234"></a> * If the background color for the element is defined as a hexadecimal value,
<a name="line235"></a> * the resulting string can be parsed by goog.color.parse in all supported
<a name="line236"></a> * browsers.
<a name="line237"></a> *
<a name="line238"></a> * Whether named colors like &quot;red&quot; or &quot;lightblue&quot; get translated into a
<a name="line239"></a> * format which can be parsed is browser dependent. Calling this function on
<a name="line240"></a> * transparent elements will return &quot;transparent&quot; in most browsers or
<a name="line241"></a> * &quot;rgba(0, 0, 0, 0)&quot; in WebKit.
<a name="line242"></a> * @param {Element} element The element to get the background color of.
<a name="line243"></a> * @return {string} The computed string value of the background color.
<a name="line244"></a> */
<a name="line245"></a>goog.style.getBackgroundColor = function(element) {
<a name="line246"></a>  return goog.style.getStyle_(element, &#39;backgroundColor&#39;);
<a name="line247"></a>};
<a name="line248"></a>
<a name="line249"></a>
<a name="line250"></a>/**
<a name="line251"></a> * Retrieves the computed value of the overflow-x CSS attribute.
<a name="line252"></a> * @param {Element} element The element to get the overflow-x of.
<a name="line253"></a> * @return {string} The computed string value of the overflow-x attribute.
<a name="line254"></a> */
<a name="line255"></a>goog.style.getComputedOverflowX = function(element) {
<a name="line256"></a>  return goog.style.getStyle_(element, &#39;overflowX&#39;);
<a name="line257"></a>};
<a name="line258"></a>
<a name="line259"></a>
<a name="line260"></a>/**
<a name="line261"></a> * Retrieves the computed value of the overflow-y CSS attribute.
<a name="line262"></a> * @param {Element} element The element to get the overflow-y of.
<a name="line263"></a> * @return {string} The computed string value of the overflow-y attribute.
<a name="line264"></a> */
<a name="line265"></a>goog.style.getComputedOverflowY = function(element) {
<a name="line266"></a>  return goog.style.getStyle_(element, &#39;overflowY&#39;);
<a name="line267"></a>};
<a name="line268"></a>
<a name="line269"></a>
<a name="line270"></a>/**
<a name="line271"></a> * Retrieves the computed value of the z-index CSS attribute.
<a name="line272"></a> * @param {Element} element The element to get the z-index of.
<a name="line273"></a> * @return {string|number} The computed value of the z-index attribute.
<a name="line274"></a> */
<a name="line275"></a>goog.style.getComputedZIndex = function(element) {
<a name="line276"></a>  return goog.style.getStyle_(element, &#39;zIndex&#39;);
<a name="line277"></a>};
<a name="line278"></a>
<a name="line279"></a>
<a name="line280"></a>/**
<a name="line281"></a> * Retrieves the computed value of the text-align CSS attribute.
<a name="line282"></a> * @param {Element} element The element to get the text-align of.
<a name="line283"></a> * @return {string} The computed string value of the text-align attribute.
<a name="line284"></a> */
<a name="line285"></a>goog.style.getComputedTextAlign = function(element) {
<a name="line286"></a>  return goog.style.getStyle_(element, &#39;textAlign&#39;);
<a name="line287"></a>};
<a name="line288"></a>
<a name="line289"></a>
<a name="line290"></a>/**
<a name="line291"></a> * Retrieves the computed value of the cursor CSS attribute.
<a name="line292"></a> * @param {Element} element The element to get the cursor of.
<a name="line293"></a> * @return {string} The computed string value of the cursor attribute.
<a name="line294"></a> */
<a name="line295"></a>goog.style.getComputedCursor = function(element) {
<a name="line296"></a>  return goog.style.getStyle_(element, &#39;cursor&#39;);
<a name="line297"></a>};
<a name="line298"></a>
<a name="line299"></a>
<a name="line300"></a>/**
<a name="line301"></a> * Sets the top/left values of an element.  If no unit is specified in the
<a name="line302"></a> * argument then it will add px. The second argument is required if the first
<a name="line303"></a> * argument is a string or number and is ignored if the first argument
<a name="line304"></a> * is a coordinate.
<a name="line305"></a> * @param {Element} el Element to move.
<a name="line306"></a> * @param {string|number|goog.math.Coordinate} arg1 Left position or coordinate.
<a name="line307"></a> * @param {string|number=} opt_arg2 Top position.
<a name="line308"></a> */
<a name="line309"></a>goog.style.setPosition = function(el, arg1, opt_arg2) {
<a name="line310"></a>  var x, y;
<a name="line311"></a>  var buggyGeckoSubPixelPos = goog.userAgent.GECKO &amp;&amp;
<a name="line312"></a>      (goog.userAgent.MAC || goog.userAgent.X11) &amp;&amp;
<a name="line313"></a>      goog.userAgent.isVersion(&#39;1.9&#39;);
<a name="line314"></a>
<a name="line315"></a>  if (arg1 instanceof goog.math.Coordinate) {
<a name="line316"></a>    x = arg1.x;
<a name="line317"></a>    y = arg1.y;
<a name="line318"></a>  } else {
<a name="line319"></a>    x = arg1;
<a name="line320"></a>    y = opt_arg2;
<a name="line321"></a>  }
<a name="line322"></a>
<a name="line323"></a>  // Round to the nearest pixel for buggy sub-pixel support.
<a name="line324"></a>  el.style.left = goog.style.getPixelStyleValue_(
<a name="line325"></a>      /** @type {number|string} */ (x), buggyGeckoSubPixelPos);
<a name="line326"></a>  el.style.top = goog.style.getPixelStyleValue_(
<a name="line327"></a>      /** @type {number|string} */ (y), buggyGeckoSubPixelPos);
<a name="line328"></a>};
<a name="line329"></a>
<a name="line330"></a>
<a name="line331"></a>/**
<a name="line332"></a> * Gets the offsetLeft and offsetTop properties of an element and returns them
<a name="line333"></a> * in a Coordinate object
<a name="line334"></a> * @param {Element} element Element.
<a name="line335"></a> * @return {!goog.math.Coordinate} The position.
<a name="line336"></a> */
<a name="line337"></a>goog.style.getPosition = function(element) {
<a name="line338"></a>  return new goog.math.Coordinate(element.offsetLeft, element.offsetTop);
<a name="line339"></a>};
<a name="line340"></a>
<a name="line341"></a>
<a name="line342"></a>/**
<a name="line343"></a> * Returns the viewport element for a particular document
<a name="line344"></a> * @param {Node=} opt_node DOM node (Document is OK) to get the viewport element
<a name="line345"></a> *     of.
<a name="line346"></a> * @return {Element} document.documentElement or document.body.
<a name="line347"></a> */
<a name="line348"></a>goog.style.getClientViewportElement = function(opt_node) {
<a name="line349"></a>  var doc;
<a name="line350"></a>  if (opt_node) {
<a name="line351"></a>    doc = goog.dom.getOwnerDocument(opt_node);
<a name="line352"></a>  } else {
<a name="line353"></a>    doc = goog.dom.getDocument();
<a name="line354"></a>  }
<a name="line355"></a>
<a name="line356"></a>  // In old IE versions the document.body represented the viewport
<a name="line357"></a>  if (goog.userAgent.IE &amp;&amp; !goog.userAgent.isDocumentMode(9) &amp;&amp;
<a name="line358"></a>      !goog.dom.getDomHelper(doc).isCss1CompatMode()) {
<a name="line359"></a>    return doc.body;
<a name="line360"></a>  }
<a name="line361"></a>  return doc.documentElement;
<a name="line362"></a>};
<a name="line363"></a>
<a name="line364"></a>
<a name="line365"></a>/**
<a name="line366"></a> * Calculates the viewport coordinates relative to the page/document
<a name="line367"></a> * containing the node. The viewport may be the browser viewport for
<a name="line368"></a> * non-iframe document, or the iframe container for iframe&#39;d document.
<a name="line369"></a> * @param {!Document} doc The document to use as the reference point.
<a name="line370"></a> * @return {!goog.math.Coordinate} The page offset of the viewport.
<a name="line371"></a> */
<a name="line372"></a>goog.style.getViewportPageOffset = function(doc) {
<a name="line373"></a>  var body = doc.body;
<a name="line374"></a>  var documentElement = doc.documentElement;
<a name="line375"></a>  var scrollLeft = body.scrollLeft || documentElement.scrollLeft;
<a name="line376"></a>  var scrollTop = body.scrollTop || documentElement.scrollTop;
<a name="line377"></a>  return new goog.math.Coordinate(scrollLeft, scrollTop);
<a name="line378"></a>};
<a name="line379"></a>
<a name="line380"></a>
<a name="line381"></a>/**
<a name="line382"></a> * Gets the client rectangle of the DOM element.
<a name="line383"></a> *
<a name="line384"></a> * getBoundingClientRect is part of a new CSS object model draft (with a
<a name="line385"></a> * long-time presence in IE), replacing the error-prone parent offset
<a name="line386"></a> * computation and the now-deprecated Gecko getBoxObjectFor.
<a name="line387"></a> *
<a name="line388"></a> * This utility patches common browser bugs in getBoundingClientRect. It
<a name="line389"></a> * will fail if getBoundingClientRect is unsupported.
<a name="line390"></a> *
<a name="line391"></a> * If the element is not in the DOM, the result is undefined, and an error may
<a name="line392"></a> * be thrown depending on user agent.
<a name="line393"></a> *
<a name="line394"></a> * @param {!Element} el The element whose bounding rectangle is being queried.
<a name="line395"></a> * @return {Object} A native bounding rectangle with numerical left, top,
<a name="line396"></a> *     right, and bottom.  Reported by Firefox to be of object type ClientRect.
<a name="line397"></a> * @private
<a name="line398"></a> */
<a name="line399"></a>goog.style.getBoundingClientRect_ = function(el) {
<a name="line400"></a>  var rect = el.getBoundingClientRect();
<a name="line401"></a>  // Patch the result in IE only, so that this function can be inlined if
<a name="line402"></a>  // compiled for non-IE.
<a name="line403"></a>  if (goog.userAgent.IE) {
<a name="line404"></a>
<a name="line405"></a>    // In IE, most of the time, 2 extra pixels are added to the top and left
<a name="line406"></a>    // due to the implicit 2-pixel inset border.  In IE6/7 quirks mode and
<a name="line407"></a>    // IE6 standards mode, this border can be overridden by setting the
<a name="line408"></a>    // document element&#39;s border to zero -- thus, we cannot rely on the
<a name="line409"></a>    // offset always being 2 pixels.
<a name="line410"></a>
<a name="line411"></a>    // In quirks mode, the offset can be determined by querying the body&#39;s
<a name="line412"></a>    // clientLeft/clientTop, but in standards mode, it is found by querying
<a name="line413"></a>    // the document element&#39;s clientLeft/clientTop.  Since we already called
<a name="line414"></a>    // getBoundingClientRect we have already forced a reflow, so it is not
<a name="line415"></a>    // too expensive just to query them all.
<a name="line416"></a>
<a name="line417"></a>    // See: http://msdn.microsoft.com/en-us/library/ms536433(VS.85).aspx
<a name="line418"></a>    var doc = el.ownerDocument;
<a name="line419"></a>    rect.left -= doc.documentElement.clientLeft + doc.body.clientLeft;
<a name="line420"></a>    rect.top -= doc.documentElement.clientTop + doc.body.clientTop;
<a name="line421"></a>  }
<a name="line422"></a>  return /** @type {Object} */ (rect);
<a name="line423"></a>};
<a name="line424"></a>
<a name="line425"></a>
<a name="line426"></a>/**
<a name="line427"></a> * Returns the first parent that could affect the position of a given element.
<a name="line428"></a> * @param {Element} element The element to get the offset parent for.
<a name="line429"></a> * @return {Element} The first offset parent or null if one cannot be found.
<a name="line430"></a> */
<a name="line431"></a>goog.style.getOffsetParent = function(element) {
<a name="line432"></a>  // element.offsetParent does the right thing in IE7 and below.  In other
<a name="line433"></a>  // browsers it only includes elements with position absolute, relative or
<a name="line434"></a>  // fixed, not elements with overflow set to auto or scroll.
<a name="line435"></a>  if (goog.userAgent.IE &amp;&amp; !goog.userAgent.isDocumentMode(8)) {
<a name="line436"></a>    return element.offsetParent;
<a name="line437"></a>  }
<a name="line438"></a>
<a name="line439"></a>  var doc = goog.dom.getOwnerDocument(element);
<a name="line440"></a>  var positionStyle = goog.style.getStyle_(element, &#39;position&#39;);
<a name="line441"></a>  var skipStatic = positionStyle == &#39;fixed&#39; || positionStyle == &#39;absolute&#39;;
<a name="line442"></a>  for (var parent = element.parentNode; parent &amp;&amp; parent != doc;
<a name="line443"></a>       parent = parent.parentNode) {
<a name="line444"></a>    positionStyle =
<a name="line445"></a>        goog.style.getStyle_(/** @type {!Element} */ (parent), &#39;position&#39;);
<a name="line446"></a>    skipStatic = skipStatic &amp;&amp; positionStyle == &#39;static&#39; &amp;&amp;
<a name="line447"></a>                 parent != doc.documentElement &amp;&amp; parent != doc.body;
<a name="line448"></a>    if (!skipStatic &amp;&amp; (parent.scrollWidth &gt; parent.clientWidth ||
<a name="line449"></a>                        parent.scrollHeight &gt; parent.clientHeight ||
<a name="line450"></a>                        positionStyle == &#39;fixed&#39; ||
<a name="line451"></a>                        positionStyle == &#39;absolute&#39; ||
<a name="line452"></a>                        positionStyle == &#39;relative&#39;)) {
<a name="line453"></a>      return /** @type {!Element} */ (parent);
<a name="line454"></a>    }
<a name="line455"></a>  }
<a name="line456"></a>  return null;
<a name="line457"></a>};
<a name="line458"></a>
<a name="line459"></a>
<a name="line460"></a>/**
<a name="line461"></a> * Calculates and returns the visible rectangle for a given element. Returns a
<a name="line462"></a> * box describing the visible portion of the nearest scrollable offset ancestor.
<a name="line463"></a> * Coordinates are given relative to the document.
<a name="line464"></a> *
<a name="line465"></a> * @param {Element} element Element to get the visible rect for.
<a name="line466"></a> * @return {goog.math.Box} Bounding elementBox describing the visible rect or
<a name="line467"></a> *     null if scrollable ancestor isn&#39;t inside the visible viewport.
<a name="line468"></a> */
<a name="line469"></a>goog.style.getVisibleRectForElement = function(element) {
<a name="line470"></a>  var visibleRect = new goog.math.Box(0, Infinity, Infinity, 0);
<a name="line471"></a>  var dom = goog.dom.getDomHelper(element);
<a name="line472"></a>  var body = dom.getDocument().body;
<a name="line473"></a>  var documentElement = dom.getDocument().documentElement;
<a name="line474"></a>  var scrollEl = dom.getDocumentScrollElement();
<a name="line475"></a>
<a name="line476"></a>  // Determine the size of the visible rect by climbing the dom accounting for
<a name="line477"></a>  // all scrollable containers.
<a name="line478"></a>  for (var el = element; el = goog.style.getOffsetParent(el); ) {
<a name="line479"></a>    // clientWidth is zero for inline block elements in IE.
<a name="line480"></a>    // on WEBKIT, body element can have clientHeight = 0 and scrollHeight &gt; 0
<a name="line481"></a>    if ((!goog.userAgent.IE || el.clientWidth != 0) &amp;&amp;
<a name="line482"></a>        (!goog.userAgent.WEBKIT || el.clientHeight != 0 || el != body) &amp;&amp;
<a name="line483"></a>        // body may have overflow set on it, yet we still get the entire
<a name="line484"></a>        // viewport. In some browsers, el.offsetParent may be
<a name="line485"></a>        // document.documentElement, so check for that too.
<a name="line486"></a>        (el != body &amp;&amp; el != documentElement &amp;&amp;
<a name="line487"></a>            goog.style.getStyle_(el, &#39;overflow&#39;) != &#39;visible&#39;)) {
<a name="line488"></a>      var pos = goog.style.getPageOffset(el);
<a name="line489"></a>      var client = goog.style.getClientLeftTop(el);
<a name="line490"></a>      pos.x += client.x;
<a name="line491"></a>      pos.y += client.y;
<a name="line492"></a>
<a name="line493"></a>      visibleRect.top = Math.max(visibleRect.top, pos.y);
<a name="line494"></a>      visibleRect.right = Math.min(visibleRect.right,
<a name="line495"></a>                                   pos.x + el.clientWidth);
<a name="line496"></a>      visibleRect.bottom = Math.min(visibleRect.bottom,
<a name="line497"></a>                                    pos.y + el.clientHeight);
<a name="line498"></a>      visibleRect.left = Math.max(visibleRect.left, pos.x);
<a name="line499"></a>    }
<a name="line500"></a>  }
<a name="line501"></a>
<a name="line502"></a>  // Clip by window&#39;s viewport.
<a name="line503"></a>  var scrollX = scrollEl.scrollLeft, scrollY = scrollEl.scrollTop;
<a name="line504"></a>  visibleRect.left = Math.max(visibleRect.left, scrollX);
<a name="line505"></a>  visibleRect.top = Math.max(visibleRect.top, scrollY);
<a name="line506"></a>  var winSize = dom.getViewportSize();
<a name="line507"></a>  visibleRect.right = Math.min(visibleRect.right, scrollX + winSize.width);
<a name="line508"></a>  visibleRect.bottom = Math.min(visibleRect.bottom, scrollY + winSize.height);
<a name="line509"></a>  return visibleRect.top &gt;= 0 &amp;&amp; visibleRect.left &gt;= 0 &amp;&amp;
<a name="line510"></a>         visibleRect.bottom &gt; visibleRect.top &amp;&amp;
<a name="line511"></a>         visibleRect.right &gt; visibleRect.left ?
<a name="line512"></a>         visibleRect : null;
<a name="line513"></a>};
<a name="line514"></a>
<a name="line515"></a>
<a name="line516"></a>/**
<a name="line517"></a> * Calculate the scroll position of {@code container} with the minimum amount so
<a name="line518"></a> * that the content and the borders of the given {@code element} become visible.
<a name="line519"></a> * If the element is bigger than the container, its top left corner will be
<a name="line520"></a> * aligned as close to the container&#39;s top left corner as possible.
<a name="line521"></a> *
<a name="line522"></a> * @param {Element} element The element to make visible.
<a name="line523"></a> * @param {Element} container The container to scroll.
<a name="line524"></a> * @param {boolean=} opt_center Whether to center the element in the container.
<a name="line525"></a> *     Defaults to false.
<a name="line526"></a> * @return {!goog.math.Coordinate} The new scroll position of the container,
<a name="line527"></a> *     in form of goog.math.Coordinate(scrollLeft, scrollTop).
<a name="line528"></a> */
<a name="line529"></a>goog.style.getContainerOffsetToScrollInto =
<a name="line530"></a>    function(element, container, opt_center) {
<a name="line531"></a>  // Absolute position of the element&#39;s border&#39;s top left corner.
<a name="line532"></a>  var elementPos = goog.style.getPageOffset(element);
<a name="line533"></a>  // Absolute position of the container&#39;s border&#39;s top left corner.
<a name="line534"></a>  var containerPos = goog.style.getPageOffset(container);
<a name="line535"></a>  var containerBorder = goog.style.getBorderBox(container);
<a name="line536"></a>  // Relative pos. of the element&#39;s border box to the container&#39;s content box.
<a name="line537"></a>  var relX = elementPos.x - containerPos.x - containerBorder.left;
<a name="line538"></a>  var relY = elementPos.y - containerPos.y - containerBorder.top;
<a name="line539"></a>  // How much the element can move in the container, i.e. the difference between
<a name="line540"></a>  // the element&#39;s bottom-right-most and top-left-most position where it&#39;s
<a name="line541"></a>  // fully visible.
<a name="line542"></a>  var spaceX = container.clientWidth - element.offsetWidth;
<a name="line543"></a>  var spaceY = container.clientHeight - element.offsetHeight;
<a name="line544"></a>
<a name="line545"></a>  var scrollLeft = container.scrollLeft;
<a name="line546"></a>  var scrollTop = container.scrollTop;
<a name="line547"></a>  if (opt_center) {
<a name="line548"></a>    // All browsers round non-integer scroll positions down.
<a name="line549"></a>    scrollLeft += relX - spaceX / 2;
<a name="line550"></a>    scrollTop += relY - spaceY / 2;
<a name="line551"></a>  } else {
<a name="line552"></a>    // This formula was designed to give the correct scroll values in the
<a name="line553"></a>    // following cases:
<a name="line554"></a>    // - element is higher than container (spaceY &lt; 0) =&gt; scroll down by relY
<a name="line555"></a>    // - element is not higher that container (spaceY &gt;= 0):
<a name="line556"></a>    //   - it is above container (relY &lt; 0) =&gt; scroll up by abs(relY)
<a name="line557"></a>    //   - it is below container (relY &gt; spaceY) =&gt; scroll down by relY - spaceY
<a name="line558"></a>    //   - it is in the container =&gt; don&#39;t scroll
<a name="line559"></a>    scrollLeft += Math.min(relX, Math.max(relX - spaceX, 0));
<a name="line560"></a>    scrollTop += Math.min(relY, Math.max(relY - spaceY, 0));
<a name="line561"></a>  }
<a name="line562"></a>  return new goog.math.Coordinate(scrollLeft, scrollTop);
<a name="line563"></a>};
<a name="line564"></a>
<a name="line565"></a>
<a name="line566"></a>/**
<a name="line567"></a> * Changes the scroll position of {@code container} with the minimum amount so
<a name="line568"></a> * that the content and the borders of the given {@code element} become visible.
<a name="line569"></a> * If the element is bigger than the container, its top left corner will be
<a name="line570"></a> * aligned as close to the container&#39;s top left corner as possible.
<a name="line571"></a> *
<a name="line572"></a> * @param {Element} element The element to make visible.
<a name="line573"></a> * @param {Element} container The container to scroll.
<a name="line574"></a> * @param {boolean=} opt_center Whether to center the element in the container.
<a name="line575"></a> *     Defaults to false.
<a name="line576"></a> */
<a name="line577"></a>goog.style.scrollIntoContainerView = function(element, container, opt_center) {
<a name="line578"></a>  var offset =
<a name="line579"></a>      goog.style.getContainerOffsetToScrollInto(element, container, opt_center);
<a name="line580"></a>  container.scrollLeft = offset.x;
<a name="line581"></a>  container.scrollTop = offset.y;
<a name="line582"></a>};
<a name="line583"></a>
<a name="line584"></a>
<a name="line585"></a>/**
<a name="line586"></a> * Returns clientLeft (width of the left border and, if the directionality is
<a name="line587"></a> * right to left, the vertical scrollbar) and clientTop as a coordinate object.
<a name="line588"></a> *
<a name="line589"></a> * @param {Element} el Element to get clientLeft for.
<a name="line590"></a> * @return {!goog.math.Coordinate} Client left and top.
<a name="line591"></a> */
<a name="line592"></a>goog.style.getClientLeftTop = function(el) {
<a name="line593"></a>  // NOTE(eae): Gecko prior to 1.9 doesn&#39;t support clientTop/Left, see
<a name="line594"></a>  // https://bugzilla.mozilla.org/show_bug.cgi?id=111207
<a name="line595"></a>  if (goog.userAgent.GECKO &amp;&amp; !goog.userAgent.isVersion(&#39;1.9&#39;)) {
<a name="line596"></a>    var left = parseFloat(goog.style.getComputedStyle(el, &#39;borderLeftWidth&#39;));
<a name="line597"></a>    if (goog.style.isRightToLeft(el)) {
<a name="line598"></a>      var scrollbarWidth = el.offsetWidth - el.clientWidth - left -
<a name="line599"></a>          parseFloat(goog.style.getComputedStyle(el, &#39;borderRightWidth&#39;));
<a name="line600"></a>      left += scrollbarWidth;
<a name="line601"></a>    }
<a name="line602"></a>    return new goog.math.Coordinate(left,
<a name="line603"></a>        parseFloat(goog.style.getComputedStyle(el, &#39;borderTopWidth&#39;)));
<a name="line604"></a>  }
<a name="line605"></a>
<a name="line606"></a>  return new goog.math.Coordinate(el.clientLeft, el.clientTop);
<a name="line607"></a>};
<a name="line608"></a>
<a name="line609"></a>
<a name="line610"></a>/**
<a name="line611"></a> * Returns a Coordinate object relative to the top-left of the HTML document.
<a name="line612"></a> * Implemented as a single function to save having to do two recursive loops in
<a name="line613"></a> * opera and safari just to get both coordinates.  If you just want one value do
<a name="line614"></a> * use goog.style.getPageOffsetLeft() and goog.style.getPageOffsetTop(), but
<a name="line615"></a> * note if you call both those methods the tree will be analysed twice.
<a name="line616"></a> *
<a name="line617"></a> * @param {Element} el Element to get the page offset for.
<a name="line618"></a> * @return {!goog.math.Coordinate} The page offset.
<a name="line619"></a> */
<a name="line620"></a>goog.style.getPageOffset = function(el) {
<a name="line621"></a>  var box, doc = goog.dom.getOwnerDocument(el);
<a name="line622"></a>  var positionStyle = goog.style.getStyle_(el, &#39;position&#39;);
<a name="line623"></a>  // TODO(gboyer): Update the jsdoc in a way that doesn&#39;t break the universe.
<a name="line624"></a>  goog.asserts.assertObject(el, &#39;Parameter is required&#39;);
<a name="line625"></a>
<a name="line626"></a>  // NOTE(eae): Gecko pre 1.9 normally use getBoxObjectFor to calculate the
<a name="line627"></a>  // position. When invoked for an element with position absolute and a negative
<a name="line628"></a>  // position though it can be off by one. Therefor the recursive implementation
<a name="line629"></a>  // is used in those (relatively rare) cases.
<a name="line630"></a>  var BUGGY_GECKO_BOX_OBJECT = goog.userAgent.GECKO &amp;&amp; doc.getBoxObjectFor &amp;&amp;
<a name="line631"></a>      !el.getBoundingClientRect &amp;&amp; positionStyle == &#39;absolute&#39; &amp;&amp;
<a name="line632"></a>      (box = doc.getBoxObjectFor(el)) &amp;&amp; (box.screenX &lt; 0 || box.screenY &lt; 0);
<a name="line633"></a>
<a name="line634"></a>  // NOTE(arv): If element is hidden (display none or disconnected or any the
<a name="line635"></a>  // ancestors are hidden) we get (0,0) by default but we still do the
<a name="line636"></a>  // accumulation of scroll position.
<a name="line637"></a>
<a name="line638"></a>  // TODO(arv): Should we check if the node is disconnected and in that case
<a name="line639"></a>  //            return (0,0)?
<a name="line640"></a>
<a name="line641"></a>  var pos = new goog.math.Coordinate(0, 0);
<a name="line642"></a>  var viewportElement = goog.style.getClientViewportElement(doc);
<a name="line643"></a>  if (el == viewportElement) {
<a name="line644"></a>    // viewport is always at 0,0 as that defined the coordinate system for this
<a name="line645"></a>    // function - this avoids special case checks in the code below
<a name="line646"></a>    return pos;
<a name="line647"></a>  }
<a name="line648"></a>
<a name="line649"></a>  // IE, Gecko 1.9+, and most modern WebKit.
<a name="line650"></a>  if (el.getBoundingClientRect) {
<a name="line651"></a>    box = goog.style.getBoundingClientRect_(el);
<a name="line652"></a>    // Must add the scroll coordinates in to get the absolute page offset
<a name="line653"></a>    // of element since getBoundingClientRect returns relative coordinates to
<a name="line654"></a>    // the viewport.
<a name="line655"></a>    var scrollCoord = goog.dom.getDomHelper(doc).getDocumentScroll();
<a name="line656"></a>    pos.x = box.left + scrollCoord.x;
<a name="line657"></a>    pos.y = box.top + scrollCoord.y;
<a name="line658"></a>
<a name="line659"></a>  // Gecko prior to 1.9.
<a name="line660"></a>  } else if (doc.getBoxObjectFor &amp;&amp; !BUGGY_GECKO_BOX_OBJECT) {
<a name="line661"></a>    // Gecko ignores the scroll values for ancestors, up to 1.9.  See:
<a name="line662"></a>    // https://bugzilla.mozilla.org/show_bug.cgi?id=328881 and
<a name="line663"></a>    // https://bugzilla.mozilla.org/show_bug.cgi?id=330619
<a name="line664"></a>
<a name="line665"></a>    box = doc.getBoxObjectFor(el);
<a name="line666"></a>    // TODO(user): Fix the off-by-one error when window is scrolled down
<a name="line667"></a>    // or right more than 1 pixel. The viewport offset does not move in lock
<a name="line668"></a>    // step with the window scroll; it moves in increments of 2px and at
<a name="line669"></a>    // somewhat random intervals.
<a name="line670"></a>    var vpBox = doc.getBoxObjectFor(viewportElement);
<a name="line671"></a>    pos.x = box.screenX - vpBox.screenX;
<a name="line672"></a>    pos.y = box.screenY - vpBox.screenY;
<a name="line673"></a>
<a name="line674"></a>  // Safari, Opera and Camino up to 1.0.4.
<a name="line675"></a>  } else {
<a name="line676"></a>    var parent = el;
<a name="line677"></a>    do {
<a name="line678"></a>      pos.x += parent.offsetLeft;
<a name="line679"></a>      pos.y += parent.offsetTop;
<a name="line680"></a>      // For safari/chrome, we need to add parent&#39;s clientLeft/Top as well.
<a name="line681"></a>      if (parent != el) {
<a name="line682"></a>        pos.x += parent.clientLeft || 0;
<a name="line683"></a>        pos.y += parent.clientTop || 0;
<a name="line684"></a>      }
<a name="line685"></a>      // In Safari when hit a position fixed element the rest of the offsets
<a name="line686"></a>      // are not correct.
<a name="line687"></a>      if (goog.userAgent.WEBKIT &amp;&amp;
<a name="line688"></a>          goog.style.getComputedPosition(parent) == &#39;fixed&#39;) {
<a name="line689"></a>        pos.x += doc.body.scrollLeft;
<a name="line690"></a>        pos.y += doc.body.scrollTop;
<a name="line691"></a>        break;
<a name="line692"></a>      }
<a name="line693"></a>      parent = parent.offsetParent;
<a name="line694"></a>    } while (parent &amp;&amp; parent != el);
<a name="line695"></a>
<a name="line696"></a>    // Opera &amp; (safari absolute) incorrectly account for body offsetTop.
<a name="line697"></a>    if (goog.userAgent.OPERA || (goog.userAgent.WEBKIT &amp;&amp;
<a name="line698"></a>        positionStyle == &#39;absolute&#39;)) {
<a name="line699"></a>      pos.y -= doc.body.offsetTop;
<a name="line700"></a>    }
<a name="line701"></a>
<a name="line702"></a>    for (parent = el; (parent = goog.style.getOffsetParent(parent)) &amp;&amp;
<a name="line703"></a>        parent != doc.body &amp;&amp; parent != viewportElement; ) {
<a name="line704"></a>      pos.x -= parent.scrollLeft;
<a name="line705"></a>      // Workaround for a bug in Opera 9.2 (and earlier) where table rows may
<a name="line706"></a>      // report an invalid scroll top value. The bug was fixed in Opera 9.5
<a name="line707"></a>      // however as that version supports getBoundingClientRect it won&#39;t
<a name="line708"></a>      // trigger this code path. https://bugs.opera.com/show_bug.cgi?id=249965
<a name="line709"></a>      if (!goog.userAgent.OPERA || parent.tagName != &#39;TR&#39;) {
<a name="line710"></a>        pos.y -= parent.scrollTop;
<a name="line711"></a>      }
<a name="line712"></a>    }
<a name="line713"></a>  }
<a name="line714"></a>
<a name="line715"></a>  return pos;
<a name="line716"></a>};
<a name="line717"></a>
<a name="line718"></a>
<a name="line719"></a>/**
<a name="line720"></a> * Returns the left coordinate of an element relative to the HTML document
<a name="line721"></a> * @param {Element} el Elements.
<a name="line722"></a> * @return {number} The left coordinate.
<a name="line723"></a> */
<a name="line724"></a>goog.style.getPageOffsetLeft = function(el) {
<a name="line725"></a>  return goog.style.getPageOffset(el).x;
<a name="line726"></a>};
<a name="line727"></a>
<a name="line728"></a>
<a name="line729"></a>/**
<a name="line730"></a> * Returns the top coordinate of an element relative to the HTML document
<a name="line731"></a> * @param {Element} el Elements.
<a name="line732"></a> * @return {number} The top coordinate.
<a name="line733"></a> */
<a name="line734"></a>goog.style.getPageOffsetTop = function(el) {
<a name="line735"></a>  return goog.style.getPageOffset(el).y;
<a name="line736"></a>};
<a name="line737"></a>
<a name="line738"></a>
<a name="line739"></a>/**
<a name="line740"></a> * Returns a Coordinate object relative to the top-left of an HTML document
<a name="line741"></a> * in an ancestor frame of this element. Used for measuring the position of
<a name="line742"></a> * an element inside a frame relative to a containing frame.
<a name="line743"></a> *
<a name="line744"></a> * @param {Element} el Element to get the page offset for.
<a name="line745"></a> * @param {Window} relativeWin The window to measure relative to. If relativeWin
<a name="line746"></a> *     is not in the ancestor frame chain of the element, we measure relative to
<a name="line747"></a> *     the top-most window.
<a name="line748"></a> * @return {!goog.math.Coordinate} The page offset.
<a name="line749"></a> */
<a name="line750"></a>goog.style.getFramedPageOffset = function(el, relativeWin) {
<a name="line751"></a>  var position = new goog.math.Coordinate(0, 0);
<a name="line752"></a>
<a name="line753"></a>  // Iterate up the ancestor frame chain, keeping track of the current window
<a name="line754"></a>  // and the current element in that window.
<a name="line755"></a>  var currentWin = goog.dom.getWindow(goog.dom.getOwnerDocument(el));
<a name="line756"></a>  var currentEl = el;
<a name="line757"></a>  do {
<a name="line758"></a>    // if we&#39;re at the top window, we want to get the page offset.
<a name="line759"></a>    // if we&#39;re at an inner frame, we only want to get the window position
<a name="line760"></a>    // so that we can determine the actual page offset in the context of
<a name="line761"></a>    // the outer window.
<a name="line762"></a>    var offset = currentWin == relativeWin ?
<a name="line763"></a>        goog.style.getPageOffset(currentEl) :
<a name="line764"></a>        goog.style.getClientPosition(currentEl);
<a name="line765"></a>
<a name="line766"></a>    position.x += offset.x;
<a name="line767"></a>    position.y += offset.y;
<a name="line768"></a>  } while (currentWin &amp;&amp; currentWin != relativeWin &amp;&amp;
<a name="line769"></a>      (currentEl = currentWin.frameElement) &amp;&amp;
<a name="line770"></a>      (currentWin = currentWin.parent));
<a name="line771"></a>
<a name="line772"></a>  return position;
<a name="line773"></a>};
<a name="line774"></a>
<a name="line775"></a>
<a name="line776"></a>/**
<a name="line777"></a> * Translates the specified rect relative to origBase page, for newBase page.
<a name="line778"></a> * If origBase and newBase are the same, this function does nothing.
<a name="line779"></a> *
<a name="line780"></a> * @param {goog.math.Rect} rect The source rectangle relative to origBase page,
<a name="line781"></a> *     and it will have the translated result.
<a name="line782"></a> * @param {goog.dom.DomHelper} origBase The DomHelper for the input rectangle.
<a name="line783"></a> * @param {goog.dom.DomHelper} newBase The DomHelper for the resultant
<a name="line784"></a> *     coordinate.  This must be a DOM for an ancestor frame of origBase
<a name="line785"></a> *     or the same as origBase.
<a name="line786"></a> */
<a name="line787"></a>goog.style.translateRectForAnotherFrame = function(rect, origBase, newBase) {
<a name="line788"></a>  if (origBase.getDocument() != newBase.getDocument()) {
<a name="line789"></a>    var body = origBase.getDocument().body;
<a name="line790"></a>    var pos = goog.style.getFramedPageOffset(body, newBase.getWindow());
<a name="line791"></a>
<a name="line792"></a>    // Adjust Body&#39;s margin.
<a name="line793"></a>    pos = goog.math.Coordinate.difference(pos, goog.style.getPageOffset(body));
<a name="line794"></a>
<a name="line795"></a>    if (goog.userAgent.IE &amp;&amp; !origBase.isCss1CompatMode()) {
<a name="line796"></a>      pos = goog.math.Coordinate.difference(pos, origBase.getDocumentScroll());
<a name="line797"></a>    }
<a name="line798"></a>
<a name="line799"></a>    rect.left += pos.x;
<a name="line800"></a>    rect.top += pos.y;
<a name="line801"></a>  }
<a name="line802"></a>};
<a name="line803"></a>
<a name="line804"></a>
<a name="line805"></a>/**
<a name="line806"></a> * Returns the position of an element relative to another element in the
<a name="line807"></a> * document.  A relative to B
<a name="line808"></a> * @param {Element|Event|goog.events.Event} a Element or mouse event whose
<a name="line809"></a> *     position we&#39;re calculating.
<a name="line810"></a> * @param {Element|Event|goog.events.Event} b Element or mouse event position
<a name="line811"></a> *     is relative to.
<a name="line812"></a> * @return {!goog.math.Coordinate} The relative position.
<a name="line813"></a> */
<a name="line814"></a>goog.style.getRelativePosition = function(a, b) {
<a name="line815"></a>  var ap = goog.style.getClientPosition(a);
<a name="line816"></a>  var bp = goog.style.getClientPosition(b);
<a name="line817"></a>  return new goog.math.Coordinate(ap.x - bp.x, ap.y - bp.y);
<a name="line818"></a>};
<a name="line819"></a>
<a name="line820"></a>
<a name="line821"></a>/**
<a name="line822"></a> * Returns the position of the event or the element&#39;s border box relative to
<a name="line823"></a> * the client viewport.
<a name="line824"></a> * @param {Element|Event|goog.events.Event} el Element or a mouse / touch event.
<a name="line825"></a> * @return {!goog.math.Coordinate} The position.
<a name="line826"></a> */
<a name="line827"></a>goog.style.getClientPosition = function(el) {
<a name="line828"></a>  var pos = new goog.math.Coordinate;
<a name="line829"></a>  if (el.nodeType == goog.dom.NodeType.ELEMENT) {
<a name="line830"></a>    el = /** @type {!Element} */ (el);
<a name="line831"></a>    if (el.getBoundingClientRect) {
<a name="line832"></a>      // IE, Gecko 1.9+, and most modern WebKit
<a name="line833"></a>      var box = goog.style.getBoundingClientRect_(el);
<a name="line834"></a>      pos.x = box.left;
<a name="line835"></a>      pos.y = box.top;
<a name="line836"></a>    } else {
<a name="line837"></a>      var scrollCoord = goog.dom.getDomHelper(el).getDocumentScroll();
<a name="line838"></a>      var pageCoord = goog.style.getPageOffset(el);
<a name="line839"></a>      pos.x = pageCoord.x - scrollCoord.x;
<a name="line840"></a>      pos.y = pageCoord.y - scrollCoord.y;
<a name="line841"></a>    }
<a name="line842"></a>    if (goog.userAgent.GECKO &amp;&amp; !goog.userAgent.isVersion(12)) {
<a name="line843"></a>      pos = goog.math.Coordinate.sum(pos, goog.style.getCssTranslation(el));
<a name="line844"></a>    }
<a name="line845"></a>  } else {
<a name="line846"></a>    var isAbstractedEvent = goog.isFunction(el.getBrowserEvent);
<a name="line847"></a>    var targetEvent = el;
<a name="line848"></a>
<a name="line849"></a>    if (el.targetTouches) {
<a name="line850"></a>      targetEvent = el.targetTouches[0];
<a name="line851"></a>    } else if (isAbstractedEvent &amp;&amp; el.getBrowserEvent().targetTouches) {
<a name="line852"></a>      targetEvent = el.getBrowserEvent().targetTouches[0];
<a name="line853"></a>    }
<a name="line854"></a>
<a name="line855"></a>    pos.x = targetEvent.clientX;
<a name="line856"></a>    pos.y = targetEvent.clientY;
<a name="line857"></a>  }
<a name="line858"></a>
<a name="line859"></a>  return pos;
<a name="line860"></a>};
<a name="line861"></a>
<a name="line862"></a>
<a name="line863"></a>/**
<a name="line864"></a> * Moves an element to the given coordinates relative to the client viewport.
<a name="line865"></a> * @param {Element} el Absolutely positioned element to set page offset for.
<a name="line866"></a> *     It must be in the document.
<a name="line867"></a> * @param {number|goog.math.Coordinate} x Left position of the element&#39;s margin
<a name="line868"></a> *     box or a coordinate object.
<a name="line869"></a> * @param {number=} opt_y Top position of the element&#39;s margin box.
<a name="line870"></a> */
<a name="line871"></a>goog.style.setPageOffset = function(el, x, opt_y) {
<a name="line872"></a>  // Get current pageoffset
<a name="line873"></a>  var cur = goog.style.getPageOffset(el);
<a name="line874"></a>
<a name="line875"></a>  if (x instanceof goog.math.Coordinate) {
<a name="line876"></a>    opt_y = x.y;
<a name="line877"></a>    x = x.x;
<a name="line878"></a>  }
<a name="line879"></a>
<a name="line880"></a>  // NOTE(arv): We cannot allow strings for x and y. We could but that would
<a name="line881"></a>  // require us to manually transform between different units
<a name="line882"></a>
<a name="line883"></a>  // Work out deltas
<a name="line884"></a>  var dx = x - cur.x;
<a name="line885"></a>  var dy = opt_y - cur.y;
<a name="line886"></a>
<a name="line887"></a>  // Set position to current left/top + delta
<a name="line888"></a>  goog.style.setPosition(el, el.offsetLeft + dx, el.offsetTop + dy);
<a name="line889"></a>};
<a name="line890"></a>
<a name="line891"></a>
<a name="line892"></a>/**
<a name="line893"></a> * Sets the width/height values of an element.  If an argument is numeric,
<a name="line894"></a> * or a goog.math.Size is passed, it is assumed to be pixels and will add
<a name="line895"></a> * &#39;px&#39; after converting it to an integer in string form. (This just sets the
<a name="line896"></a> * CSS width and height properties so it might set content-box or border-box
<a name="line897"></a> * size depending on the box model the browser is using.)
<a name="line898"></a> *
<a name="line899"></a> * @param {Element} element Element to set the size of.
<a name="line900"></a> * @param {string|number|goog.math.Size} w Width of the element, or a
<a name="line901"></a> *     size object.
<a name="line902"></a> * @param {string|number=} opt_h Height of the element. Required if w is not a
<a name="line903"></a> *     size object.
<a name="line904"></a> */
<a name="line905"></a>goog.style.setSize = function(element, w, opt_h) {
<a name="line906"></a>  var h;
<a name="line907"></a>  if (w instanceof goog.math.Size) {
<a name="line908"></a>    h = w.height;
<a name="line909"></a>    w = w.width;
<a name="line910"></a>  } else {
<a name="line911"></a>    if (opt_h == undefined) {
<a name="line912"></a>      throw Error(&#39;missing height argument&#39;);
<a name="line913"></a>    }
<a name="line914"></a>    h = opt_h;
<a name="line915"></a>  }
<a name="line916"></a>
<a name="line917"></a>  goog.style.setWidth(element, /** @type {string|number} */ (w));
<a name="line918"></a>  goog.style.setHeight(element, /** @type {string|number} */ (h));
<a name="line919"></a>};
<a name="line920"></a>
<a name="line921"></a>
<a name="line922"></a>/**
<a name="line923"></a> * Helper function to create a string to be set into a pixel-value style
<a name="line924"></a> * property of an element. Can round to the nearest integer value.
<a name="line925"></a> *
<a name="line926"></a> * @param {string|number} value The style value to be used. If a number,
<a name="line927"></a> *     &#39;px&#39; will be appended, otherwise the value will be applied directly.
<a name="line928"></a> * @param {boolean} round Whether to round the nearest integer (if property
<a name="line929"></a> *     is a number).
<a name="line930"></a> * @return {string} The string value for the property.
<a name="line931"></a> * @private
<a name="line932"></a> */
<a name="line933"></a>goog.style.getPixelStyleValue_ = function(value, round) {
<a name="line934"></a>  if (typeof value == &#39;number&#39;) {
<a name="line935"></a>    value = (round ? Math.round(value) : value) + &#39;px&#39;;
<a name="line936"></a>  }
<a name="line937"></a>
<a name="line938"></a>  return value;
<a name="line939"></a>};
<a name="line940"></a>
<a name="line941"></a>
<a name="line942"></a>/**
<a name="line943"></a> * Set the height of an element.  Sets the element&#39;s style property.
<a name="line944"></a> * @param {Element} element Element to set the height of.
<a name="line945"></a> * @param {string|number} height The height value to set.  If a number, &#39;px&#39;
<a name="line946"></a> *     will be appended, otherwise the value will be applied directly.
<a name="line947"></a> */
<a name="line948"></a>goog.style.setHeight = function(element, height) {
<a name="line949"></a>  element.style.height = goog.style.getPixelStyleValue_(height, true);
<a name="line950"></a>};
<a name="line951"></a>
<a name="line952"></a>
<a name="line953"></a>/**
<a name="line954"></a> * Set the width of an element.  Sets the element&#39;s style property.
<a name="line955"></a> * @param {Element} element Element to set the width of.
<a name="line956"></a> * @param {string|number} width The width value to set.  If a number, &#39;px&#39;
<a name="line957"></a> *     will be appended, otherwise the value will be applied directly.
<a name="line958"></a> */
<a name="line959"></a>goog.style.setWidth = function(element, width) {
<a name="line960"></a>  element.style.width = goog.style.getPixelStyleValue_(width, true);
<a name="line961"></a>};
<a name="line962"></a>
<a name="line963"></a>
<a name="line964"></a>/**
<a name="line965"></a> * Gets the height and width of an element, even if its display is none.
<a name="line966"></a> * Specifically, this returns the height and width of the border box,
<a name="line967"></a> * irrespective of the box model in effect.
<a name="line968"></a> * @param {Element} element Element to get size of.
<a name="line969"></a> * @return {!goog.math.Size} Object with width/height properties.
<a name="line970"></a> */
<a name="line971"></a>goog.style.getSize = function(element) {
<a name="line972"></a>  if (goog.style.getStyle_(element, &#39;display&#39;) != &#39;none&#39;) {
<a name="line973"></a>    return goog.style.getSizeWithDisplay_(element);
<a name="line974"></a>  }
<a name="line975"></a>
<a name="line976"></a>  var style = element.style;
<a name="line977"></a>  var originalDisplay = style.display;
<a name="line978"></a>  var originalVisibility = style.visibility;
<a name="line979"></a>  var originalPosition = style.position;
<a name="line980"></a>
<a name="line981"></a>  style.visibility = &#39;hidden&#39;;
<a name="line982"></a>  style.position = &#39;absolute&#39;;
<a name="line983"></a>  style.display = &#39;inline&#39;;
<a name="line984"></a>
<a name="line985"></a>  var size = goog.style.getSizeWithDisplay_(element);
<a name="line986"></a>
<a name="line987"></a>  style.display = originalDisplay;
<a name="line988"></a>  style.position = originalPosition;
<a name="line989"></a>  style.visibility = originalVisibility;
<a name="line990"></a>
<a name="line991"></a>  return size;
<a name="line992"></a>};
<a name="line993"></a>
<a name="line994"></a>
<a name="line995"></a>/**
<a name="line996"></a> * Gets the height and with of an element when the display is not none.
<a name="line997"></a> * @param {Element} element Element to get size of.
<a name="line998"></a> * @return {!goog.math.Size} Object with width/height properties.
<a name="line999"></a> * @private
<a name="line1000"></a> */
<a name="line1001"></a>goog.style.getSizeWithDisplay_ = function(element) {
<a name="line1002"></a>  var offsetWidth = element.offsetWidth;
<a name="line1003"></a>  var offsetHeight = element.offsetHeight;
<a name="line1004"></a>  var webkitOffsetsZero =
<a name="line1005"></a>      goog.userAgent.WEBKIT &amp;&amp; !offsetWidth &amp;&amp; !offsetHeight;
<a name="line1006"></a>  if ((!goog.isDef(offsetWidth) || webkitOffsetsZero) &amp;&amp;
<a name="line1007"></a>      element.getBoundingClientRect) {
<a name="line1008"></a>    // Fall back to calling getBoundingClientRect when offsetWidth or
<a name="line1009"></a>    // offsetHeight are not defined, or when they are zero in WebKit browsers.
<a name="line1010"></a>    // This makes sure that we return for the correct size for SVG elements, but
<a name="line1011"></a>    // will still return 0 on Webkit prior to 534.8, see
<a name="line1012"></a>    // http://trac.webkit.org/changeset/67252.
<a name="line1013"></a>    var clientRect = goog.style.getBoundingClientRect_(element);
<a name="line1014"></a>    return new goog.math.Size(clientRect.right - clientRect.left,
<a name="line1015"></a>        clientRect.bottom - clientRect.top);
<a name="line1016"></a>  }
<a name="line1017"></a>  return new goog.math.Size(offsetWidth, offsetHeight);
<a name="line1018"></a>};
<a name="line1019"></a>
<a name="line1020"></a>
<a name="line1021"></a>/**
<a name="line1022"></a> * Returns a bounding rectangle for a given element in page space.
<a name="line1023"></a> * @param {Element} element Element to get bounds of. Must not be display none.
<a name="line1024"></a> * @return {!goog.math.Rect} Bounding rectangle for the element.
<a name="line1025"></a> */
<a name="line1026"></a>goog.style.getBounds = function(element) {
<a name="line1027"></a>  var o = goog.style.getPageOffset(element);
<a name="line1028"></a>  var s = goog.style.getSize(element);
<a name="line1029"></a>  return new goog.math.Rect(o.x, o.y, s.width, s.height);
<a name="line1030"></a>};
<a name="line1031"></a>
<a name="line1032"></a>
<a name="line1033"></a>/**
<a name="line1034"></a> * Converts a CSS selector in the form style-property to styleProperty.
<a name="line1035"></a> * @param {*} selector CSS Selector.
<a name="line1036"></a> * @return {string} Camel case selector.
<a name="line1037"></a> * @deprecated Use goog.string.toCamelCase instead.
<a name="line1038"></a> */
<a name="line1039"></a>goog.style.toCamelCase = function(selector) {
<a name="line1040"></a>  return goog.string.toCamelCase(String(selector));
<a name="line1041"></a>};
<a name="line1042"></a>
<a name="line1043"></a>
<a name="line1044"></a>/**
<a name="line1045"></a> * Converts a CSS selector in the form styleProperty to style-property.
<a name="line1046"></a> * @param {string} selector Camel case selector.
<a name="line1047"></a> * @return {string} Selector cased.
<a name="line1048"></a> * @deprecated Use goog.string.toSelectorCase instead.
<a name="line1049"></a> */
<a name="line1050"></a>goog.style.toSelectorCase = function(selector) {
<a name="line1051"></a>  return goog.string.toSelectorCase(selector);
<a name="line1052"></a>};
<a name="line1053"></a>
<a name="line1054"></a>
<a name="line1055"></a>/**
<a name="line1056"></a> * Gets the opacity of a node (x-browser). This gets the inline style opacity
<a name="line1057"></a> * of the node, and does not take into account the cascaded or the computed
<a name="line1058"></a> * style for this node.
<a name="line1059"></a> * @param {Element} el Element whose opacity has to be found.
<a name="line1060"></a> * @return {number|string} Opacity between 0 and 1 or an empty string {@code &#39;&#39;}
<a name="line1061"></a> *     if the opacity is not set.
<a name="line1062"></a> */
<a name="line1063"></a>goog.style.getOpacity = function(el) {
<a name="line1064"></a>  var style = el.style;
<a name="line1065"></a>  var result = &#39;&#39;;
<a name="line1066"></a>  if (&#39;opacity&#39; in style) {
<a name="line1067"></a>    result = style.opacity;
<a name="line1068"></a>  } else if (&#39;MozOpacity&#39; in style) {
<a name="line1069"></a>    result = style.MozOpacity;
<a name="line1070"></a>  } else if (&#39;filter&#39; in style) {
<a name="line1071"></a>    var match = style.filter.match(/alpha\(opacity=([\d.]+)\)/);
<a name="line1072"></a>    if (match) {
<a name="line1073"></a>      result = String(match[1] / 100);
<a name="line1074"></a>    }
<a name="line1075"></a>  }
<a name="line1076"></a>  return result == &#39;&#39; ? result : Number(result);
<a name="line1077"></a>};
<a name="line1078"></a>
<a name="line1079"></a>
<a name="line1080"></a>/**
<a name="line1081"></a> * Sets the opacity of a node (x-browser).
<a name="line1082"></a> * @param {Element} el Elements whose opacity has to be set.
<a name="line1083"></a> * @param {number|string} alpha Opacity between 0 and 1 or an empty string
<a name="line1084"></a> *     {@code &#39;&#39;} to clear the opacity.
<a name="line1085"></a> */
<a name="line1086"></a>goog.style.setOpacity = function(el, alpha) {
<a name="line1087"></a>  var style = el.style;
<a name="line1088"></a>  if (&#39;opacity&#39; in style) {
<a name="line1089"></a>    style.opacity = alpha;
<a name="line1090"></a>  } else if (&#39;MozOpacity&#39; in style) {
<a name="line1091"></a>    style.MozOpacity = alpha;
<a name="line1092"></a>  } else if (&#39;filter&#39; in style) {
<a name="line1093"></a>    // TODO(arv): Overwriting the filter might have undesired side effects.
<a name="line1094"></a>    if (alpha === &#39;&#39;) {
<a name="line1095"></a>      style.filter = &#39;&#39;;
<a name="line1096"></a>    } else {
<a name="line1097"></a>      style.filter = &#39;alpha(opacity=&#39; + alpha * 100 + &#39;)&#39;;
<a name="line1098"></a>    }
<a name="line1099"></a>  }
<a name="line1100"></a>};
<a name="line1101"></a>
<a name="line1102"></a>
<a name="line1103"></a>/**
<a name="line1104"></a> * Sets the background of an element to a transparent image in a browser-
<a name="line1105"></a> * independent manner.
<a name="line1106"></a> *
<a name="line1107"></a> * This function does not support repeating backgrounds or alternate background
<a name="line1108"></a> * positions to match the behavior of Internet Explorer. It also does not
<a name="line1109"></a> * support sizingMethods other than crop since they cannot be replicated in
<a name="line1110"></a> * browsers other than Internet Explorer.
<a name="line1111"></a> *
<a name="line1112"></a> * @param {Element} el The element to set background on.
<a name="line1113"></a> * @param {string} src The image source URL.
<a name="line1114"></a> */
<a name="line1115"></a>goog.style.setTransparentBackgroundImage = function(el, src) {
<a name="line1116"></a>  var style = el.style;
<a name="line1117"></a>  // It is safe to use the style.filter in IE only. In Safari &#39;filter&#39; is in
<a name="line1118"></a>  // style object but access to style.filter causes it to throw an exception.
<a name="line1119"></a>  // Note: IE8 supports images with an alpha channel.
<a name="line1120"></a>  if (goog.userAgent.IE &amp;&amp; !goog.userAgent.isVersion(&#39;8&#39;)) {
<a name="line1121"></a>    // See TODO in setOpacity.
<a name="line1122"></a>    style.filter = &#39;progid:DXImageTransform.Microsoft.AlphaImageLoader(&#39; +
<a name="line1123"></a>        &#39;src=&quot;&#39; + src + &#39;&quot;, sizingMethod=&quot;crop&quot;)&#39;;
<a name="line1124"></a>  } else {
<a name="line1125"></a>    // Set style properties individually instead of using background shorthand
<a name="line1126"></a>    // to prevent overwriting a pre-existing background color.
<a name="line1127"></a>    style.backgroundImage = &#39;url(&#39; + src + &#39;)&#39;;
<a name="line1128"></a>    style.backgroundPosition = &#39;top left&#39;;
<a name="line1129"></a>    style.backgroundRepeat = &#39;no-repeat&#39;;
<a name="line1130"></a>  }
<a name="line1131"></a>};
<a name="line1132"></a>
<a name="line1133"></a>
<a name="line1134"></a>/**
<a name="line1135"></a> * Clears the background image of an element in a browser independent manner.
<a name="line1136"></a> * @param {Element} el The element to clear background image for.
<a name="line1137"></a> */
<a name="line1138"></a>goog.style.clearTransparentBackgroundImage = function(el) {
<a name="line1139"></a>  var style = el.style;
<a name="line1140"></a>  if (&#39;filter&#39; in style) {
<a name="line1141"></a>    // See TODO in setOpacity.
<a name="line1142"></a>    style.filter = &#39;&#39;;
<a name="line1143"></a>  } else {
<a name="line1144"></a>    // Set style properties individually instead of using background shorthand
<a name="line1145"></a>    // to prevent overwriting a pre-existing background color.
<a name="line1146"></a>    style.backgroundImage = &#39;none&#39;;
<a name="line1147"></a>  }
<a name="line1148"></a>};
<a name="line1149"></a>
<a name="line1150"></a>
<a name="line1151"></a>/**
<a name="line1152"></a> * Shows or hides an element from the page. Hiding the element is done by
<a name="line1153"></a> * setting the display property to &quot;none&quot;, removing the element from the
<a name="line1154"></a> * rendering hierarchy so it takes up no space. To show the element, the default
<a name="line1155"></a> * inherited display property is restored (defined either in stylesheets or by
<a name="line1156"></a> * the browser&#39;s default style rules.)
<a name="line1157"></a> *
<a name="line1158"></a> * Caveat 1: if the inherited display property for the element is set to &quot;none&quot;
<a name="line1159"></a> * by the stylesheets, that is the property that will be restored by a call to
<a name="line1160"></a> * showElement(), effectively toggling the display between &quot;none&quot; and &quot;none&quot;.
<a name="line1161"></a> *
<a name="line1162"></a> * Caveat 2: if the element display style is set inline (by setting either
<a name="line1163"></a> * element.style.display or a style attribute in the HTML), a call to
<a name="line1164"></a> * showElement will clear that setting and defer to the inherited style in the
<a name="line1165"></a> * stylesheet.
<a name="line1166"></a> * @param {Element} el Element to show or hide.
<a name="line1167"></a> * @param {*} display True to render the element in its default style,
<a name="line1168"></a> * false to disable rendering the element.
<a name="line1169"></a> */
<a name="line1170"></a>goog.style.showElement = function(el, display) {
<a name="line1171"></a>  el.style.display = display ? &#39;&#39; : &#39;none&#39;;
<a name="line1172"></a>};
<a name="line1173"></a>
<a name="line1174"></a>
<a name="line1175"></a>/**
<a name="line1176"></a> * Test whether the given element has been shown or hidden via a call to
<a name="line1177"></a> * {@link #showElement}.
<a name="line1178"></a> *
<a name="line1179"></a> * Note this is strictly a companion method for a call
<a name="line1180"></a> * to {@link #showElement} and the same caveats apply; in particular, this
<a name="line1181"></a> * method does not guarantee that the return value will be consistent with
<a name="line1182"></a> * whether or not the element is actually visible.
<a name="line1183"></a> *
<a name="line1184"></a> * @param {Element} el The element to test.
<a name="line1185"></a> * @return {boolean} Whether the element has been shown.
<a name="line1186"></a> * @see #showElement
<a name="line1187"></a> */
<a name="line1188"></a>goog.style.isElementShown = function(el) {
<a name="line1189"></a>  return el.style.display != &#39;none&#39;;
<a name="line1190"></a>};
<a name="line1191"></a>
<a name="line1192"></a>
<a name="line1193"></a>/**
<a name="line1194"></a> * Installs the styles string into the window that contains opt_element.  If
<a name="line1195"></a> * opt_element is null, the main window is used.
<a name="line1196"></a> * @param {string} stylesString The style string to install.
<a name="line1197"></a> * @param {Node=} opt_node Node whose parent document should have the
<a name="line1198"></a> *     styles installed.
<a name="line1199"></a> * @return {Element|StyleSheet} The style element created.
<a name="line1200"></a> */
<a name="line1201"></a>goog.style.installStyles = function(stylesString, opt_node) {
<a name="line1202"></a>  var dh = goog.dom.getDomHelper(opt_node);
<a name="line1203"></a>  var styleSheet = null;
<a name="line1204"></a>
<a name="line1205"></a>  if (goog.userAgent.IE) {
<a name="line1206"></a>    styleSheet = dh.getDocument().createStyleSheet();
<a name="line1207"></a>    goog.style.setStyles(styleSheet, stylesString);
<a name="line1208"></a>  } else {
<a name="line1209"></a>    var head = dh.getElementsByTagNameAndClass(&#39;head&#39;)[0];
<a name="line1210"></a>
<a name="line1211"></a>    // In opera documents are not guaranteed to have a head element, thus we
<a name="line1212"></a>    // have to make sure one exists before using it.
<a name="line1213"></a>    if (!head) {
<a name="line1214"></a>      var body = dh.getElementsByTagNameAndClass(&#39;body&#39;)[0];
<a name="line1215"></a>      head = dh.createDom(&#39;head&#39;);
<a name="line1216"></a>      body.parentNode.insertBefore(head, body);
<a name="line1217"></a>    }
<a name="line1218"></a>    styleSheet = dh.createDom(&#39;style&#39;);
<a name="line1219"></a>    // NOTE(user): Setting styles after the style element has been appended
<a name="line1220"></a>    // to the head results in a nasty Webkit bug in certain scenarios. Please
<a name="line1221"></a>    // refer to https://bugs.webkit.org/show_bug.cgi?id=26307 for additional
<a name="line1222"></a>    // details.
<a name="line1223"></a>    goog.style.setStyles(styleSheet, stylesString);
<a name="line1224"></a>    dh.appendChild(head, styleSheet);
<a name="line1225"></a>  }
<a name="line1226"></a>  return styleSheet;
<a name="line1227"></a>};
<a name="line1228"></a>
<a name="line1229"></a>
<a name="line1230"></a>/**
<a name="line1231"></a> * Removes the styles added by {@link #installStyles}.
<a name="line1232"></a> * @param {Element|StyleSheet} styleSheet The value returned by
<a name="line1233"></a> *     {@link #installStyles}.
<a name="line1234"></a> */
<a name="line1235"></a>goog.style.uninstallStyles = function(styleSheet) {
<a name="line1236"></a>  var node = styleSheet.ownerNode || styleSheet.owningElement ||
<a name="line1237"></a>      /** @type {Element} */ (styleSheet);
<a name="line1238"></a>  goog.dom.removeNode(node);
<a name="line1239"></a>};
<a name="line1240"></a>
<a name="line1241"></a>
<a name="line1242"></a>/**
<a name="line1243"></a> * Sets the content of a style element.  The style element can be any valid
<a name="line1244"></a> * style element.  This element will have its content completely replaced by
<a name="line1245"></a> * the new stylesString.
<a name="line1246"></a> * @param {Element|StyleSheet} element A stylesheet element as returned by
<a name="line1247"></a> *     installStyles.
<a name="line1248"></a> * @param {string} stylesString The new content of the stylesheet.
<a name="line1249"></a> */
<a name="line1250"></a>goog.style.setStyles = function(element, stylesString) {
<a name="line1251"></a>  if (goog.userAgent.IE) {
<a name="line1252"></a>    // Adding the selectors individually caused the browser to hang if the
<a name="line1253"></a>    // selector was invalid or there were CSS comments.  Setting the cssText of
<a name="line1254"></a>    // the style node works fine and ignores CSS that IE doesn&#39;t understand
<a name="line1255"></a>    element.cssText = stylesString;
<a name="line1256"></a>  } else {
<a name="line1257"></a>    element.innerHTML = stylesString;
<a name="line1258"></a>  }
<a name="line1259"></a>};
<a name="line1260"></a>
<a name="line1261"></a>
<a name="line1262"></a>/**
<a name="line1263"></a> * Sets &#39;white-space: pre-wrap&#39; for a node (x-browser).
<a name="line1264"></a> *
<a name="line1265"></a> * There are as many ways of specifying pre-wrap as there are browsers.
<a name="line1266"></a> *
<a name="line1267"></a> * CSS3/IE8: white-space: pre-wrap;
<a name="line1268"></a> * Mozilla:  white-space: -moz-pre-wrap;
<a name="line1269"></a> * Opera:    white-space: -o-pre-wrap;
<a name="line1270"></a> * IE6/7:    white-space: pre; word-wrap: break-word;
<a name="line1271"></a> *
<a name="line1272"></a> * @param {Element} el Element to enable pre-wrap for.
<a name="line1273"></a> */
<a name="line1274"></a>goog.style.setPreWrap = function(el) {
<a name="line1275"></a>  var style = el.style;
<a name="line1276"></a>  if (goog.userAgent.IE &amp;&amp; !goog.userAgent.isVersion(&#39;8&#39;)) {
<a name="line1277"></a>    style.whiteSpace = &#39;pre&#39;;
<a name="line1278"></a>    style.wordWrap = &#39;break-word&#39;;
<a name="line1279"></a>  } else if (goog.userAgent.GECKO) {
<a name="line1280"></a>    style.whiteSpace = &#39;-moz-pre-wrap&#39;;
<a name="line1281"></a>  } else {
<a name="line1282"></a>    style.whiteSpace = &#39;pre-wrap&#39;;
<a name="line1283"></a>  }
<a name="line1284"></a>};
<a name="line1285"></a>
<a name="line1286"></a>
<a name="line1287"></a>/**
<a name="line1288"></a> * Sets &#39;display: inline-block&#39; for an element (cross-browser).
<a name="line1289"></a> * @param {Element} el Element to which the inline-block display style is to be
<a name="line1290"></a> *    applied.
<a name="line1291"></a> * @see ../demos/inline_block_quirks.html
<a name="line1292"></a> * @see ../demos/inline_block_standards.html
<a name="line1293"></a> */
<a name="line1294"></a>goog.style.setInlineBlock = function(el) {
<a name="line1295"></a>  var style = el.style;
<a name="line1296"></a>  // Without position:relative, weirdness ensues.  Just accept it and move on.
<a name="line1297"></a>  style.position = &#39;relative&#39;;
<a name="line1298"></a>
<a name="line1299"></a>  if (goog.userAgent.IE &amp;&amp; !goog.userAgent.isVersion(&#39;8&#39;)) {
<a name="line1300"></a>    // IE8 supports inline-block so fall through to the else
<a name="line1301"></a>    // Zoom:1 forces hasLayout, display:inline gives inline behavior.
<a name="line1302"></a>    style.zoom = &#39;1&#39;;
<a name="line1303"></a>    style.display = &#39;inline&#39;;
<a name="line1304"></a>  } else if (goog.userAgent.GECKO) {
<a name="line1305"></a>    // Pre-Firefox 3, Gecko doesn&#39;t support inline-block, but -moz-inline-box
<a name="line1306"></a>    // is close enough.
<a name="line1307"></a>    style.display = goog.userAgent.isVersion(&#39;1.9a&#39;) ? &#39;inline-block&#39; :
<a name="line1308"></a>        &#39;-moz-inline-box&#39;;
<a name="line1309"></a>  } else {
<a name="line1310"></a>    // Opera, Webkit, and Safari seem to do OK with the standard inline-block
<a name="line1311"></a>    // style.
<a name="line1312"></a>    style.display = &#39;inline-block&#39;;
<a name="line1313"></a>  }
<a name="line1314"></a>};
<a name="line1315"></a>
<a name="line1316"></a>
<a name="line1317"></a>/**
<a name="line1318"></a> * Returns true if the element is using right to left (rtl) direction.
<a name="line1319"></a> * @param {Element} el  The element to test.
<a name="line1320"></a> * @return {boolean} True for right to left, false for left to right.
<a name="line1321"></a> */
<a name="line1322"></a>goog.style.isRightToLeft = function(el) {
<a name="line1323"></a>  return &#39;rtl&#39; == goog.style.getStyle_(el, &#39;direction&#39;);
<a name="line1324"></a>};
<a name="line1325"></a>
<a name="line1326"></a>
<a name="line1327"></a>/**
<a name="line1328"></a> * The CSS style property corresponding to an element being
<a name="line1329"></a> * unselectable on the current browser platform (null if none).
<a name="line1330"></a> * Opera and IE instead use a DOM attribute &#39;unselectable&#39;.
<a name="line1331"></a> * @type {?string}
<a name="line1332"></a> * @private
<a name="line1333"></a> */
<a name="line1334"></a>goog.style.unselectableStyle_ =
<a name="line1335"></a>    goog.userAgent.GECKO ? &#39;MozUserSelect&#39; :
<a name="line1336"></a>    goog.userAgent.WEBKIT ? &#39;WebkitUserSelect&#39; :
<a name="line1337"></a>    null;
<a name="line1338"></a>
<a name="line1339"></a>
<a name="line1340"></a>/**
<a name="line1341"></a> * Returns true if the element is set to be unselectable, false otherwise.
<a name="line1342"></a> * Note that on some platforms (e.g. Mozilla), even if an element isn&#39;t set
<a name="line1343"></a> * to be unselectable, it will behave as such if any of its ancestors is
<a name="line1344"></a> * unselectable.
<a name="line1345"></a> * @param {Element} el  Element to check.
<a name="line1346"></a> * @return {boolean}  Whether the element is set to be unselectable.
<a name="line1347"></a> */
<a name="line1348"></a>goog.style.isUnselectable = function(el) {
<a name="line1349"></a>  if (goog.style.unselectableStyle_) {
<a name="line1350"></a>    return el.style[goog.style.unselectableStyle_].toLowerCase() == &#39;none&#39;;
<a name="line1351"></a>  } else if (goog.userAgent.IE || goog.userAgent.OPERA) {
<a name="line1352"></a>    return el.getAttribute(&#39;unselectable&#39;) == &#39;on&#39;;
<a name="line1353"></a>  }
<a name="line1354"></a>  return false;
<a name="line1355"></a>};
<a name="line1356"></a>
<a name="line1357"></a>
<a name="line1358"></a>/**
<a name="line1359"></a> * Makes the element and its descendants selectable or unselectable.  Note
<a name="line1360"></a> * that on some platforms (e.g. Mozilla), even if an element isn&#39;t set to
<a name="line1361"></a> * be unselectable, it will behave as such if any of its ancestors is
<a name="line1362"></a> * unselectable.
<a name="line1363"></a> * @param {Element} el  The element to alter.
<a name="line1364"></a> * @param {boolean} unselectable  Whether the element and its descendants
<a name="line1365"></a> *     should be made unselectable.
<a name="line1366"></a> * @param {boolean=} opt_noRecurse  Whether to only alter the element&#39;s own
<a name="line1367"></a> *     selectable state, and leave its descendants alone; defaults to false.
<a name="line1368"></a> */
<a name="line1369"></a>goog.style.setUnselectable = function(el, unselectable, opt_noRecurse) {
<a name="line1370"></a>  // TODO(attila): Do we need all of TR_DomUtil.makeUnselectable() in Closure?
<a name="line1371"></a>  var descendants = !opt_noRecurse ? el.getElementsByTagName(&#39;*&#39;) : null;
<a name="line1372"></a>  var name = goog.style.unselectableStyle_;
<a name="line1373"></a>  if (name) {
<a name="line1374"></a>    // Add/remove the appropriate CSS style to/from the element and its
<a name="line1375"></a>    // descendants.
<a name="line1376"></a>    var value = unselectable ? &#39;none&#39; : &#39;&#39;;
<a name="line1377"></a>    el.style[name] = value;
<a name="line1378"></a>    if (descendants) {
<a name="line1379"></a>      for (var i = 0, descendant; descendant = descendants[i]; i++) {
<a name="line1380"></a>        descendant.style[name] = value;
<a name="line1381"></a>      }
<a name="line1382"></a>    }
<a name="line1383"></a>  } else if (goog.userAgent.IE || goog.userAgent.OPERA) {
<a name="line1384"></a>    // Toggle the &#39;unselectable&#39; attribute on the element and its descendants.
<a name="line1385"></a>    var value = unselectable ? &#39;on&#39; : &#39;&#39;;
<a name="line1386"></a>    el.setAttribute(&#39;unselectable&#39;, value);
<a name="line1387"></a>    if (descendants) {
<a name="line1388"></a>      for (var i = 0, descendant; descendant = descendants[i]; i++) {
<a name="line1389"></a>        descendant.setAttribute(&#39;unselectable&#39;, value);
<a name="line1390"></a>      }
<a name="line1391"></a>    }
<a name="line1392"></a>  }
<a name="line1393"></a>};
<a name="line1394"></a>
<a name="line1395"></a>
<a name="line1396"></a>/**
<a name="line1397"></a> * Gets the border box size for an element.
<a name="line1398"></a> * @param {Element} element  The element to get the size for.
<a name="line1399"></a> * @return {!goog.math.Size} The border box size.
<a name="line1400"></a> */
<a name="line1401"></a>goog.style.getBorderBoxSize = function(element) {
<a name="line1402"></a>  return new goog.math.Size(element.offsetWidth, element.offsetHeight);
<a name="line1403"></a>};
<a name="line1404"></a>
<a name="line1405"></a>
<a name="line1406"></a>/**
<a name="line1407"></a> * Sets the border box size of an element. This is potentially expensive in IE
<a name="line1408"></a> * if the document is CSS1Compat mode
<a name="line1409"></a> * @param {Element} element  The element to set the size on.
<a name="line1410"></a> * @param {goog.math.Size} size  The new size.
<a name="line1411"></a> */
<a name="line1412"></a>goog.style.setBorderBoxSize = function(element, size) {
<a name="line1413"></a>  var doc = goog.dom.getOwnerDocument(element);
<a name="line1414"></a>  var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode();
<a name="line1415"></a>
<a name="line1416"></a>  if (goog.userAgent.IE &amp;&amp;
<a name="line1417"></a>      (!isCss1CompatMode || !goog.userAgent.isVersion(&#39;8&#39;))) {
<a name="line1418"></a>    var style = element.style;
<a name="line1419"></a>    if (isCss1CompatMode) {
<a name="line1420"></a>      var paddingBox = goog.style.getPaddingBox(element);
<a name="line1421"></a>      var borderBox = goog.style.getBorderBox(element);
<a name="line1422"></a>      style.pixelWidth = size.width - borderBox.left - paddingBox.left -
<a name="line1423"></a>                         paddingBox.right - borderBox.right;
<a name="line1424"></a>      style.pixelHeight = size.height - borderBox.top - paddingBox.top -
<a name="line1425"></a>                          paddingBox.bottom - borderBox.bottom;
<a name="line1426"></a>    } else {
<a name="line1427"></a>      style.pixelWidth = size.width;
<a name="line1428"></a>      style.pixelHeight = size.height;
<a name="line1429"></a>    }
<a name="line1430"></a>  } else {
<a name="line1431"></a>    goog.style.setBoxSizingSize_(element, size, &#39;border-box&#39;);
<a name="line1432"></a>  }
<a name="line1433"></a>};
<a name="line1434"></a>
<a name="line1435"></a>
<a name="line1436"></a>/**
<a name="line1437"></a> * Gets the content box size for an element.  This is potentially expensive in
<a name="line1438"></a> * all browsers.
<a name="line1439"></a> * @param {Element} element  The element to get the size for.
<a name="line1440"></a> * @return {!goog.math.Size} The content box size.
<a name="line1441"></a> */
<a name="line1442"></a>goog.style.getContentBoxSize = function(element) {
<a name="line1443"></a>  var doc = goog.dom.getOwnerDocument(element);
<a name="line1444"></a>  var ieCurrentStyle = goog.userAgent.IE &amp;&amp; element.currentStyle;
<a name="line1445"></a>  if (ieCurrentStyle &amp;&amp;
<a name="line1446"></a>      goog.dom.getDomHelper(doc).isCss1CompatMode() &amp;&amp;
<a name="line1447"></a>      ieCurrentStyle.width != &#39;auto&#39; &amp;&amp; ieCurrentStyle.height != &#39;auto&#39; &amp;&amp;
<a name="line1448"></a>      !ieCurrentStyle.boxSizing) {
<a name="line1449"></a>    // If IE in CSS1Compat mode than just use the width and height.
<a name="line1450"></a>    // If we have a boxSizing then fall back on measuring the borders etc.
<a name="line1451"></a>    var width = goog.style.getIePixelValue_(element, ieCurrentStyle.width,
<a name="line1452"></a>                                            &#39;width&#39;, &#39;pixelWidth&#39;);
<a name="line1453"></a>    var height = goog.style.getIePixelValue_(element, ieCurrentStyle.height,
<a name="line1454"></a>                                             &#39;height&#39;, &#39;pixelHeight&#39;);
<a name="line1455"></a>    return new goog.math.Size(width, height);
<a name="line1456"></a>  } else {
<a name="line1457"></a>    var borderBoxSize = goog.style.getBorderBoxSize(element);
<a name="line1458"></a>    var paddingBox = goog.style.getPaddingBox(element);
<a name="line1459"></a>    var borderBox = goog.style.getBorderBox(element);
<a name="line1460"></a>    return new goog.math.Size(borderBoxSize.width -
<a name="line1461"></a>                              borderBox.left - paddingBox.left -
<a name="line1462"></a>                              paddingBox.right - borderBox.right,
<a name="line1463"></a>                              borderBoxSize.height -
<a name="line1464"></a>                              borderBox.top - paddingBox.top -
<a name="line1465"></a>                              paddingBox.bottom - borderBox.bottom);
<a name="line1466"></a>  }
<a name="line1467"></a>};
<a name="line1468"></a>
<a name="line1469"></a>
<a name="line1470"></a>/**
<a name="line1471"></a> * Sets the content box size of an element. This is potentially expensive in IE
<a name="line1472"></a> * if the document is BackCompat mode.
<a name="line1473"></a> * @param {Element} element  The element to set the size on.
<a name="line1474"></a> * @param {goog.math.Size} size  The new size.
<a name="line1475"></a> */
<a name="line1476"></a>goog.style.setContentBoxSize = function(element, size) {
<a name="line1477"></a>  var doc = goog.dom.getOwnerDocument(element);
<a name="line1478"></a>  var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode();
<a name="line1479"></a>  if (goog.userAgent.IE &amp;&amp;
<a name="line1480"></a>      (!isCss1CompatMode || !goog.userAgent.isVersion(&#39;8&#39;))) {
<a name="line1481"></a>    var style = element.style;
<a name="line1482"></a>    if (isCss1CompatMode) {
<a name="line1483"></a>      style.pixelWidth = size.width;
<a name="line1484"></a>      style.pixelHeight = size.height;
<a name="line1485"></a>    } else {
<a name="line1486"></a>      var paddingBox = goog.style.getPaddingBox(element);
<a name="line1487"></a>      var borderBox = goog.style.getBorderBox(element);
<a name="line1488"></a>      style.pixelWidth = size.width + borderBox.left + paddingBox.left +
<a name="line1489"></a>                         paddingBox.right + borderBox.right;
<a name="line1490"></a>      style.pixelHeight = size.height + borderBox.top + paddingBox.top +
<a name="line1491"></a>                          paddingBox.bottom + borderBox.bottom;
<a name="line1492"></a>    }
<a name="line1493"></a>  } else {
<a name="line1494"></a>    goog.style.setBoxSizingSize_(element, size, &#39;content-box&#39;);
<a name="line1495"></a>  }
<a name="line1496"></a>};
<a name="line1497"></a>
<a name="line1498"></a>
<a name="line1499"></a>/**
<a name="line1500"></a> * Helper function that sets the box sizing as well as the width and height
<a name="line1501"></a> * @param {Element} element  The element to set the size on.
<a name="line1502"></a> * @param {goog.math.Size} size  The new size to set.
<a name="line1503"></a> * @param {string} boxSizing  The box-sizing value.
<a name="line1504"></a> * @private
<a name="line1505"></a> */
<a name="line1506"></a>goog.style.setBoxSizingSize_ = function(element, size, boxSizing) {
<a name="line1507"></a>  var style = element.style;
<a name="line1508"></a>  if (goog.userAgent.GECKO) {
<a name="line1509"></a>    style.MozBoxSizing = boxSizing;
<a name="line1510"></a>  } else if (goog.userAgent.WEBKIT) {
<a name="line1511"></a>    style.WebkitBoxSizing = boxSizing;
<a name="line1512"></a>  } else {
<a name="line1513"></a>    // Includes IE8 and Opera 9.50+
<a name="line1514"></a>    style.boxSizing = boxSizing;
<a name="line1515"></a>  }
<a name="line1516"></a>
<a name="line1517"></a>  // Setting this to a negative value will throw an exception on IE
<a name="line1518"></a>  // (and doesn&#39;t do anything different than setting it to 0).
<a name="line1519"></a>  style.width = Math.max(size.width, 0) + &#39;px&#39;;
<a name="line1520"></a>  style.height = Math.max(size.height, 0) + &#39;px&#39;;
<a name="line1521"></a>};
<a name="line1522"></a>
<a name="line1523"></a>
<a name="line1524"></a>/**
<a name="line1525"></a> * IE specific function that converts a non pixel unit to pixels.
<a name="line1526"></a> * @param {Element} element  The element to convert the value for.
<a name="line1527"></a> * @param {string} value  The current value as a string. The value must not be
<a name="line1528"></a> *     &#39;&#39;.
<a name="line1529"></a> * @param {string} name  The CSS property name to use for the converstion. This
<a name="line1530"></a> *     should be &#39;left&#39;, &#39;top&#39;, &#39;width&#39; or &#39;height&#39;.
<a name="line1531"></a> * @param {string} pixelName  The CSS pixel property name to use to get the
<a name="line1532"></a> *     value in pixels.
<a name="line1533"></a> * @return {number} The value in pixels.
<a name="line1534"></a> * @private
<a name="line1535"></a> */
<a name="line1536"></a>goog.style.getIePixelValue_ = function(element, value, name, pixelName) {
<a name="line1537"></a>  // Try if we already have a pixel value. IE does not do half pixels so we
<a name="line1538"></a>  // only check if it matches a number followed by &#39;px&#39;.
<a name="line1539"></a>  if (/^\d+px?$/.test(value)) {
<a name="line1540"></a>    return parseInt(value, 10);
<a name="line1541"></a>  } else {
<a name="line1542"></a>    var oldStyleValue = element.style[name];
<a name="line1543"></a>    var oldRuntimeValue = element.runtimeStyle[name];
<a name="line1544"></a>    // set runtime style to prevent changes
<a name="line1545"></a>    element.runtimeStyle[name] = element.currentStyle[name];
<a name="line1546"></a>    element.style[name] = value;
<a name="line1547"></a>    var pixelValue = element.style[pixelName];
<a name="line1548"></a>    // restore
<a name="line1549"></a>    element.style[name] = oldStyleValue;
<a name="line1550"></a>    element.runtimeStyle[name] = oldRuntimeValue;
<a name="line1551"></a>    return pixelValue;
<a name="line1552"></a>  }
<a name="line1553"></a>};
<a name="line1554"></a>
<a name="line1555"></a>
<a name="line1556"></a>/**
<a name="line1557"></a> * Helper function for getting the pixel padding or margin for IE.
<a name="line1558"></a> * @param {Element} element  The element to get the padding for.
<a name="line1559"></a> * @param {string} propName  The property name.
<a name="line1560"></a> * @return {number} The pixel padding.
<a name="line1561"></a> * @private
<a name="line1562"></a> */
<a name="line1563"></a>goog.style.getIePixelDistance_ = function(element, propName) {
<a name="line1564"></a>  var value = goog.style.getCascadedStyle(element, propName);
<a name="line1565"></a>  return value ?
<a name="line1566"></a>      goog.style.getIePixelValue_(element, value, &#39;left&#39;, &#39;pixelLeft&#39;) : 0;
<a name="line1567"></a>};
<a name="line1568"></a>
<a name="line1569"></a>
<a name="line1570"></a>/**
<a name="line1571"></a> * Gets the computed paddings or margins (on all sides) in pixels.
<a name="line1572"></a> * @param {Element} element  The element to get the padding for.
<a name="line1573"></a> * @param {string} stylePrefix  Pass &#39;padding&#39; to retrieve the padding box,
<a name="line1574"></a> *     or &#39;margin&#39; to retrieve the margin box.
<a name="line1575"></a> * @return {!goog.math.Box} The computed paddings or margins.
<a name="line1576"></a> * @private
<a name="line1577"></a> */
<a name="line1578"></a>goog.style.getBox_ = function(element, stylePrefix) {
<a name="line1579"></a>  if (goog.userAgent.IE) {
<a name="line1580"></a>    var left = goog.style.getIePixelDistance_(element, stylePrefix + &#39;Left&#39;);
<a name="line1581"></a>    var right = goog.style.getIePixelDistance_(element, stylePrefix + &#39;Right&#39;);
<a name="line1582"></a>    var top = goog.style.getIePixelDistance_(element, stylePrefix + &#39;Top&#39;);
<a name="line1583"></a>    var bottom = goog.style.getIePixelDistance_(
<a name="line1584"></a>        element, stylePrefix + &#39;Bottom&#39;);
<a name="line1585"></a>    return new goog.math.Box(top, right, bottom, left);
<a name="line1586"></a>  } else {
<a name="line1587"></a>    // On non-IE browsers, getComputedStyle is always non-null.
<a name="line1588"></a>    var left = /** @type {string} */ (
<a name="line1589"></a>        goog.style.getComputedStyle(element, stylePrefix + &#39;Left&#39;));
<a name="line1590"></a>    var right = /** @type {string} */ (
<a name="line1591"></a>        goog.style.getComputedStyle(element, stylePrefix + &#39;Right&#39;));
<a name="line1592"></a>    var top = /** @type {string} */ (
<a name="line1593"></a>        goog.style.getComputedStyle(element, stylePrefix + &#39;Top&#39;));
<a name="line1594"></a>    var bottom = /** @type {string} */ (
<a name="line1595"></a>        goog.style.getComputedStyle(element, stylePrefix + &#39;Bottom&#39;));
<a name="line1596"></a>
<a name="line1597"></a>    // NOTE(arv): Gecko can return floating point numbers for the computed
<a name="line1598"></a>    // style values.
<a name="line1599"></a>    return new goog.math.Box(parseFloat(top),
<a name="line1600"></a>                             parseFloat(right),
<a name="line1601"></a>                             parseFloat(bottom),
<a name="line1602"></a>                             parseFloat(left));
<a name="line1603"></a>  }
<a name="line1604"></a>};
<a name="line1605"></a>
<a name="line1606"></a>
<a name="line1607"></a>/**
<a name="line1608"></a> * Gets the computed paddings (on all sides) in pixels.
<a name="line1609"></a> * @param {Element} element  The element to get the padding for.
<a name="line1610"></a> * @return {!goog.math.Box} The computed paddings.
<a name="line1611"></a> */
<a name="line1612"></a>goog.style.getPaddingBox = function(element) {
<a name="line1613"></a>  return goog.style.getBox_(element, &#39;padding&#39;);
<a name="line1614"></a>};
<a name="line1615"></a>
<a name="line1616"></a>
<a name="line1617"></a>/**
<a name="line1618"></a> * Gets the computed margins (on all sides) in pixels.
<a name="line1619"></a> * @param {Element} element  The element to get the margins for.
<a name="line1620"></a> * @return {!goog.math.Box} The computed margins.
<a name="line1621"></a> */
<a name="line1622"></a>goog.style.getMarginBox = function(element) {
<a name="line1623"></a>  return goog.style.getBox_(element, &#39;margin&#39;);
<a name="line1624"></a>};
<a name="line1625"></a>
<a name="line1626"></a>
<a name="line1627"></a>/**
<a name="line1628"></a> * A map used to map the border width keywords to a pixel width.
<a name="line1629"></a> * @type {Object}
<a name="line1630"></a> * @private
<a name="line1631"></a> */
<a name="line1632"></a>goog.style.ieBorderWidthKeywords_ = {
<a name="line1633"></a>  &#39;thin&#39;: 2,
<a name="line1634"></a>  &#39;medium&#39;: 4,
<a name="line1635"></a>  &#39;thick&#39;: 6
<a name="line1636"></a>};
<a name="line1637"></a>
<a name="line1638"></a>
<a name="line1639"></a>/**
<a name="line1640"></a> * Helper function for IE to get the pixel border.
<a name="line1641"></a> * @param {Element} element  The element to get the pixel border for.
<a name="line1642"></a> * @param {string} prop  The part of the property name.
<a name="line1643"></a> * @return {number} The value in pixels.
<a name="line1644"></a> * @private
<a name="line1645"></a> */
<a name="line1646"></a>goog.style.getIePixelBorder_ = function(element, prop) {
<a name="line1647"></a>  if (goog.style.getCascadedStyle(element, prop + &#39;Style&#39;) == &#39;none&#39;) {
<a name="line1648"></a>    return 0;
<a name="line1649"></a>  }
<a name="line1650"></a>  var width = goog.style.getCascadedStyle(element, prop + &#39;Width&#39;);
<a name="line1651"></a>  if (width in goog.style.ieBorderWidthKeywords_) {
<a name="line1652"></a>    return goog.style.ieBorderWidthKeywords_[width];
<a name="line1653"></a>  }
<a name="line1654"></a>  return goog.style.getIePixelValue_(element, width, &#39;left&#39;, &#39;pixelLeft&#39;);
<a name="line1655"></a>};
<a name="line1656"></a>
<a name="line1657"></a>
<a name="line1658"></a>/**
<a name="line1659"></a> * Gets the computed border widths (on all sides) in pixels
<a name="line1660"></a> * @param {Element} element  The element to get the border widths for.
<a name="line1661"></a> * @return {!goog.math.Box} The computed border widths.
<a name="line1662"></a> */
<a name="line1663"></a>goog.style.getBorderBox = function(element) {
<a name="line1664"></a>  if (goog.userAgent.IE) {
<a name="line1665"></a>    var left = goog.style.getIePixelBorder_(element, &#39;borderLeft&#39;);
<a name="line1666"></a>    var right = goog.style.getIePixelBorder_(element, &#39;borderRight&#39;);
<a name="line1667"></a>    var top = goog.style.getIePixelBorder_(element, &#39;borderTop&#39;);
<a name="line1668"></a>    var bottom = goog.style.getIePixelBorder_(element, &#39;borderBottom&#39;);
<a name="line1669"></a>    return new goog.math.Box(top, right, bottom, left);
<a name="line1670"></a>  } else {
<a name="line1671"></a>    // On non-IE browsers, getComputedStyle is always non-null.
<a name="line1672"></a>    var left = /** @type {string} */ (
<a name="line1673"></a>        goog.style.getComputedStyle(element, &#39;borderLeftWidth&#39;));
<a name="line1674"></a>    var right = /** @type {string} */ (
<a name="line1675"></a>        goog.style.getComputedStyle(element, &#39;borderRightWidth&#39;));
<a name="line1676"></a>    var top = /** @type {string} */ (
<a name="line1677"></a>        goog.style.getComputedStyle(element, &#39;borderTopWidth&#39;));
<a name="line1678"></a>    var bottom = /** @type {string} */ (
<a name="line1679"></a>        goog.style.getComputedStyle(element, &#39;borderBottomWidth&#39;));
<a name="line1680"></a>
<a name="line1681"></a>    return new goog.math.Box(parseFloat(top),
<a name="line1682"></a>                             parseFloat(right),
<a name="line1683"></a>                             parseFloat(bottom),
<a name="line1684"></a>                             parseFloat(left));
<a name="line1685"></a>  }
<a name="line1686"></a>};
<a name="line1687"></a>
<a name="line1688"></a>
<a name="line1689"></a>/**
<a name="line1690"></a> * Returns the font face applied to a given node. Opera and IE should return
<a name="line1691"></a> * the font actually displayed. Firefox returns the author&#39;s most-preferred
<a name="line1692"></a> * font (whether the browser is capable of displaying it or not.)
<a name="line1693"></a> * @param {Element} el  The element whose font family is returned.
<a name="line1694"></a> * @return {string} The font family applied to el.
<a name="line1695"></a> */
<a name="line1696"></a>goog.style.getFontFamily = function(el) {
<a name="line1697"></a>  var doc = goog.dom.getOwnerDocument(el);
<a name="line1698"></a>  var font = &#39;&#39;;
<a name="line1699"></a>  if (doc.body.createTextRange) {
<a name="line1700"></a>    var range = doc.body.createTextRange();
<a name="line1701"></a>    range.moveToElementText(el);
<a name="line1702"></a>    /** @preserveTry */
<a name="line1703"></a>    try {
<a name="line1704"></a>      font = range.queryCommandValue(&#39;FontName&#39;);
<a name="line1705"></a>    } catch (e) {
<a name="line1706"></a>      // This is a workaround for a awkward exception.
<a name="line1707"></a>      // On some IE, there is an exception coming from it.
<a name="line1708"></a>      // The error description from this exception is:
<a name="line1709"></a>      // This window has already been registered as a drop target
<a name="line1710"></a>      // This is bogus description, likely due to a bug in ie.
<a name="line1711"></a>      font = &#39;&#39;;
<a name="line1712"></a>    }
<a name="line1713"></a>  }
<a name="line1714"></a>  if (!font) {
<a name="line1715"></a>    // Note if for some reason IE can&#39;t derive FontName with a TextRange, we
<a name="line1716"></a>    // fallback to using currentStyle
<a name="line1717"></a>    font = goog.style.getStyle_(el, &#39;fontFamily&#39;);
<a name="line1718"></a>  }
<a name="line1719"></a>
<a name="line1720"></a>  // Firefox returns the applied font-family string (author&#39;s list of
<a name="line1721"></a>  // preferred fonts.) We want to return the most-preferred font, in lieu of
<a name="line1722"></a>  // the *actually* applied font.
<a name="line1723"></a>  var fontsArray = font.split(&#39;,&#39;);
<a name="line1724"></a>  if (fontsArray.length &gt; 1) font = fontsArray[0];
<a name="line1725"></a>
<a name="line1726"></a>  // Sanitize for x-browser consistency:
<a name="line1727"></a>  // Strip quotes because browsers aren&#39;t consistent with how they&#39;re
<a name="line1728"></a>  // applied; Opera always encloses, Firefox sometimes, and IE never.
<a name="line1729"></a>  return goog.string.stripQuotes(font, &#39;&quot;\&#39;&#39;);
<a name="line1730"></a>};
<a name="line1731"></a>
<a name="line1732"></a>
<a name="line1733"></a>/**
<a name="line1734"></a> * Regular expression used for getLengthUnits.
<a name="line1735"></a> * @type {RegExp}
<a name="line1736"></a> * @private
<a name="line1737"></a> */
<a name="line1738"></a>goog.style.lengthUnitRegex_ = /[^\d]+$/;
<a name="line1739"></a>
<a name="line1740"></a>
<a name="line1741"></a>/**
<a name="line1742"></a> * Returns the units used for a CSS length measurement.
<a name="line1743"></a> * @param {string} value  A CSS length quantity.
<a name="line1744"></a> * @return {?string} The units of measurement.
<a name="line1745"></a> */
<a name="line1746"></a>goog.style.getLengthUnits = function(value) {
<a name="line1747"></a>  var units = value.match(goog.style.lengthUnitRegex_);
<a name="line1748"></a>  return units &amp;&amp; units[0] || null;
<a name="line1749"></a>};
<a name="line1750"></a>
<a name="line1751"></a>
<a name="line1752"></a>/**
<a name="line1753"></a> * Map of absolute CSS length units
<a name="line1754"></a> * @type {Object}
<a name="line1755"></a> * @private
<a name="line1756"></a> */
<a name="line1757"></a>goog.style.ABSOLUTE_CSS_LENGTH_UNITS_ = {
<a name="line1758"></a>  &#39;cm&#39; : 1,
<a name="line1759"></a>  &#39;in&#39; : 1,
<a name="line1760"></a>  &#39;mm&#39; : 1,
<a name="line1761"></a>  &#39;pc&#39; : 1,
<a name="line1762"></a>  &#39;pt&#39; : 1
<a name="line1763"></a>};
<a name="line1764"></a>
<a name="line1765"></a>
<a name="line1766"></a>/**
<a name="line1767"></a> * Map of relative CSS length units that can be accurately converted to px
<a name="line1768"></a> * font-size values using getIePixelValue_. Only units that are defined in
<a name="line1769"></a> * relation to a font size are convertible (%, small, etc. are not).
<a name="line1770"></a> * @type {Object}
<a name="line1771"></a> * @private
<a name="line1772"></a> */
<a name="line1773"></a>goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_ = {
<a name="line1774"></a>  &#39;em&#39; : 1,
<a name="line1775"></a>  &#39;ex&#39; : 1
<a name="line1776"></a>};
<a name="line1777"></a>
<a name="line1778"></a>
<a name="line1779"></a>/**
<a name="line1780"></a> * Returns the font size, in pixels, of text in an element.
<a name="line1781"></a> * @param {Element} el  The element whose font size is returned.
<a name="line1782"></a> * @return {number} The font size (in pixels).
<a name="line1783"></a> */
<a name="line1784"></a>goog.style.getFontSize = function(el) {
<a name="line1785"></a>  var fontSize = goog.style.getStyle_(el, &#39;fontSize&#39;);
<a name="line1786"></a>  var sizeUnits = goog.style.getLengthUnits(fontSize);
<a name="line1787"></a>  if (fontSize &amp;&amp; &#39;px&#39; == sizeUnits) {
<a name="line1788"></a>    // NOTE(user): This could be parseFloat instead, but IE doesn&#39;t return
<a name="line1789"></a>    // decimal fractions in getStyle_ and Firefox reports the fractions, but
<a name="line1790"></a>    // ignores them when rendering. Interestingly enough, when we force the
<a name="line1791"></a>    // issue and size something to e.g., 50% of 25px, the browsers round in
<a name="line1792"></a>    // opposite directions with Firefox reporting 12px and IE 13px. I punt.
<a name="line1793"></a>    return parseInt(fontSize, 10);
<a name="line1794"></a>  }
<a name="line1795"></a>
<a name="line1796"></a>  // In IE, we can convert absolute length units to a px value using
<a name="line1797"></a>  // goog.style.getIePixelValue_. Units defined in relation to a font size
<a name="line1798"></a>  // (em, ex) are applied relative to the element&#39;s parentNode and can also
<a name="line1799"></a>  // be converted.
<a name="line1800"></a>  if (goog.userAgent.IE) {
<a name="line1801"></a>    if (sizeUnits in goog.style.ABSOLUTE_CSS_LENGTH_UNITS_) {
<a name="line1802"></a>      return goog.style.getIePixelValue_(el,
<a name="line1803"></a>                                         fontSize,
<a name="line1804"></a>                                         &#39;left&#39;,
<a name="line1805"></a>                                         &#39;pixelLeft&#39;);
<a name="line1806"></a>    } else if (el.parentNode &amp;&amp;
<a name="line1807"></a>               el.parentNode.nodeType == goog.dom.NodeType.ELEMENT &amp;&amp;
<a name="line1808"></a>               sizeUnits in goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_) {
<a name="line1809"></a>      // Check the parent size - if it is the same it means the relative size
<a name="line1810"></a>      // value is inherited and we therefore don&#39;t want to count it twice.  If
<a name="line1811"></a>      // it is different, this element either has explicit style or has a CSS
<a name="line1812"></a>      // rule applying to it.
<a name="line1813"></a>      var parentElement = /** @type {Element} */ (el.parentNode);
<a name="line1814"></a>      var parentSize = goog.style.getStyle_(parentElement, &#39;fontSize&#39;);
<a name="line1815"></a>      return goog.style.getIePixelValue_(parentElement,
<a name="line1816"></a>                                         fontSize == parentSize ?
<a name="line1817"></a>                                             &#39;1em&#39; : fontSize,
<a name="line1818"></a>                                         &#39;left&#39;,
<a name="line1819"></a>                                         &#39;pixelLeft&#39;);
<a name="line1820"></a>    }
<a name="line1821"></a>  }
<a name="line1822"></a>
<a name="line1823"></a>  // Sometimes we can&#39;t cleanly find the font size (some units relative to a
<a name="line1824"></a>  // node&#39;s parent&#39;s font size are difficult: %, smaller et al), so we create
<a name="line1825"></a>  // an invisible, absolutely-positioned span sized to be the height of an &#39;M&#39;
<a name="line1826"></a>  // rendered in its parent&#39;s (i.e., our target element&#39;s) font size. This is
<a name="line1827"></a>  // the definition of CSS&#39;s font size attribute.
<a name="line1828"></a>  var sizeElement = goog.dom.createDom(
<a name="line1829"></a>      &#39;span&#39;,
<a name="line1830"></a>      {&#39;style&#39;: &#39;visibility:hidden;position:absolute;&#39; +
<a name="line1831"></a>            &#39;line-height:0;padding:0;margin:0;border:0;height:1em;&#39;});
<a name="line1832"></a>  goog.dom.appendChild(el, sizeElement);
<a name="line1833"></a>  fontSize = sizeElement.offsetHeight;
<a name="line1834"></a>  goog.dom.removeNode(sizeElement);
<a name="line1835"></a>
<a name="line1836"></a>  return fontSize;
<a name="line1837"></a>};
<a name="line1838"></a>
<a name="line1839"></a>
<a name="line1840"></a>/**
<a name="line1841"></a> * Parses a style attribute value.  Converts CSS property names to camel case.
<a name="line1842"></a> * @param {string} value The style attribute value.
<a name="line1843"></a> * @return {!Object} Map of CSS properties to string values.
<a name="line1844"></a> */
<a name="line1845"></a>goog.style.parseStyleAttribute = function(value) {
<a name="line1846"></a>  var result = {};
<a name="line1847"></a>  goog.array.forEach(value.split(/\s*;\s*/), function(pair) {
<a name="line1848"></a>    var keyValue = pair.split(/\s*:\s*/);
<a name="line1849"></a>    if (keyValue.length == 2) {
<a name="line1850"></a>      result[goog.string.toCamelCase(keyValue[0].toLowerCase())] = keyValue[1];
<a name="line1851"></a>    }
<a name="line1852"></a>  });
<a name="line1853"></a>  return result;
<a name="line1854"></a>};
<a name="line1855"></a>
<a name="line1856"></a>
<a name="line1857"></a>/**
<a name="line1858"></a> * Reverse of parseStyleAttribute; that is, takes a style object and returns the
<a name="line1859"></a> * corresponding attribute value.  Converts camel case property names to proper
<a name="line1860"></a> * CSS selector names.
<a name="line1861"></a> * @param {Object} obj Map of CSS properties to values.
<a name="line1862"></a> * @return {string} The style attribute value.
<a name="line1863"></a> */
<a name="line1864"></a>goog.style.toStyleAttribute = function(obj) {
<a name="line1865"></a>  var buffer = [];
<a name="line1866"></a>  goog.object.forEach(obj, function(value, key) {
<a name="line1867"></a>    buffer.push(goog.string.toSelectorCase(key), &#39;:&#39;, value, &#39;;&#39;);
<a name="line1868"></a>  });
<a name="line1869"></a>  return buffer.join(&#39;&#39;);
<a name="line1870"></a>};
<a name="line1871"></a>
<a name="line1872"></a>
<a name="line1873"></a>/**
<a name="line1874"></a> * Sets CSS float property on an element.
<a name="line1875"></a> * @param {Element} el The element to set float property on.
<a name="line1876"></a> * @param {string} value The value of float CSS property to set on this element.
<a name="line1877"></a> */
<a name="line1878"></a>goog.style.setFloat = function(el, value) {
<a name="line1879"></a>  el.style[goog.userAgent.IE ? &#39;styleFloat&#39; : &#39;cssFloat&#39;] = value;
<a name="line1880"></a>};
<a name="line1881"></a>
<a name="line1882"></a>
<a name="line1883"></a>/**
<a name="line1884"></a> * Gets value of explicitly-set float CSS property on an element.
<a name="line1885"></a> * @param {Element} el The element to get float property of.
<a name="line1886"></a> * @return {string} The value of explicitly-set float CSS property on this
<a name="line1887"></a> *     element.
<a name="line1888"></a> */
<a name="line1889"></a>goog.style.getFloat = function(el) {
<a name="line1890"></a>  return el.style[goog.userAgent.IE ? &#39;styleFloat&#39; : &#39;cssFloat&#39;] || &#39;&#39;;
<a name="line1891"></a>};
<a name="line1892"></a>
<a name="line1893"></a>
<a name="line1894"></a>/**
<a name="line1895"></a> * Returns the scroll bar width (represents the width of both horizontal
<a name="line1896"></a> * and vertical scroll).
<a name="line1897"></a> *
<a name="line1898"></a> * @param {string=} opt_className An optional class name (or names) to apply
<a name="line1899"></a> *     to the invisible div created to measure the scrollbar. This is necessary
<a name="line1900"></a> *     if some scrollbars are styled differently than others.
<a name="line1901"></a> * @return {number} The scroll bar width in px.
<a name="line1902"></a> */
<a name="line1903"></a>goog.style.getScrollbarWidth = function(opt_className) {
<a name="line1904"></a>  // Add two hidden divs.  The child div is larger than the parent and
<a name="line1905"></a>  // forces scrollbars to appear on it.
<a name="line1906"></a>  // Using overflow:scroll does not work consistently with scrollbars that
<a name="line1907"></a>  // are styled with ::-webkit-scrollbar.
<a name="line1908"></a>  var outerDiv = goog.dom.createElement(&#39;div&#39;);
<a name="line1909"></a>  if (opt_className) {
<a name="line1910"></a>    outerDiv.className = opt_className;
<a name="line1911"></a>  }
<a name="line1912"></a>  outerDiv.style.cssText = &#39;overflow:auto;&#39; +
<a name="line1913"></a>      &#39;position:absolute;top:0;width:100px;height:100px&#39;;
<a name="line1914"></a>  var innerDiv = goog.dom.createElement(&#39;div&#39;);
<a name="line1915"></a>  goog.style.setSize(innerDiv, &#39;200px&#39;, &#39;200px&#39;);
<a name="line1916"></a>  outerDiv.appendChild(innerDiv);
<a name="line1917"></a>  goog.dom.appendChild(goog.dom.getDocument().body, outerDiv);
<a name="line1918"></a>  var width = outerDiv.offsetWidth - outerDiv.clientWidth;
<a name="line1919"></a>  goog.dom.removeNode(outerDiv);
<a name="line1920"></a>  return width;
<a name="line1921"></a>};
<a name="line1922"></a>
<a name="line1923"></a>
<a name="line1924"></a>/**
<a name="line1925"></a> * Regular expression to extract x and y translation components from a CSS
<a name="line1926"></a> * transform Matrix representation.
<a name="line1927"></a> *
<a name="line1928"></a> * @type {!RegExp}
<a name="line1929"></a> * @const
<a name="line1930"></a> * @private
<a name="line1931"></a> */
<a name="line1932"></a>goog.style.MATRIX_TRANSLATION_REGEX_ =
<a name="line1933"></a>    new RegExp(&#39;matrix\\([0-9\\.\\-]+, [0-9\\.\\-]+, &#39; +
<a name="line1934"></a>               &#39;[0-9\\.\\-]+, [0-9\\.\\-]+, &#39; +
<a name="line1935"></a>               &#39;([0-9\\.\\-]+)p?x?, ([0-9\\.\\-]+)p?x?\\)&#39;);
<a name="line1936"></a>
<a name="line1937"></a>
<a name="line1938"></a>/**
<a name="line1939"></a> * Returns the x,y translation component of any CSS transforms applied to the
<a name="line1940"></a> * element, in pixels.
<a name="line1941"></a> *
<a name="line1942"></a> * @param {!Element} element The element to get the translation of.
<a name="line1943"></a> * @return {!goog.math.Coordinate} The CSS translation of the element in px.
<a name="line1944"></a> */
<a name="line1945"></a>goog.style.getCssTranslation = function(element) {
<a name="line1946"></a>  var property;
<a name="line1947"></a>  if (goog.userAgent.IE) {
<a name="line1948"></a>    property = &#39;-ms-transform&#39;;
<a name="line1949"></a>  } else if (goog.userAgent.WEBKIT) {
<a name="line1950"></a>    property = &#39;-webkit-transform&#39;;
<a name="line1951"></a>  } else if (goog.userAgent.OPERA) {
<a name="line1952"></a>    property = &#39;-o-transform&#39;;
<a name="line1953"></a>  } else if (goog.userAgent.GECKO) {
<a name="line1954"></a>    property = &#39;-moz-transform&#39;;
<a name="line1955"></a>  }
<a name="line1956"></a>  var transform;
<a name="line1957"></a>  if (property) {
<a name="line1958"></a>    transform = goog.style.getStyle_(element, property);
<a name="line1959"></a>  }
<a name="line1960"></a>  if (!transform) {
<a name="line1961"></a>    transform = goog.style.getStyle_(element, &#39;transform&#39;);
<a name="line1962"></a>  }
<a name="line1963"></a>  if (!transform) {
<a name="line1964"></a>    return new goog.math.Coordinate(0, 0);
<a name="line1965"></a>  }
<a name="line1966"></a>  var matches = transform.match(goog.style.MATRIX_TRANSLATION_REGEX_);
<a name="line1967"></a>  if (!matches) {
<a name="line1968"></a>    return new goog.math.Coordinate(0, 0);
<a name="line1969"></a>  }
<a name="line1970"></a>  return new goog.math.Coordinate(parseFloat(matches[1]),
<a name="line1971"></a>                                  parseFloat(matches[2]));
<a name="line1972"></a>};
</pre>


</body>
</html>
